mirror of
https://git.mirrors.martin98.com/https://github.com/langgenius/dify.git
synced 2025-08-14 22:55:54 +08:00
authorizing redirection
This commit is contained in:
parent
2bcfcfabb7
commit
8832f08fed
@ -34,8 +34,8 @@ const NewMCPCard = ({ handleCreate }: Props) => {
|
|||||||
const linkUrl = useMemo(() => {
|
const linkUrl = useMemo(() => {
|
||||||
// TODO help link
|
// TODO help link
|
||||||
if (language.startsWith('zh_'))
|
if (language.startsWith('zh_'))
|
||||||
return 'https://docs.dify.ai/zh-hans/guides/tools#ru-he-chuang-jian-zi-ding-yi-gong-ju'
|
return 'https://docs.dify.ai/zh-hans/guides/tools/integrate-tool/mcp'
|
||||||
return 'https://docs.dify.ai/en/guides/tools#how-to-create-custom-tools'
|
return 'https://docs.dify.ai/en/guides/tools/integrate-tool/mcp'
|
||||||
}, [language])
|
}, [language])
|
||||||
|
|
||||||
const [showModal, setShowModal] = useState(false)
|
const [showModal, setShowModal] = useState(false)
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import React, { useCallback, useState } from 'react'
|
import React, { useCallback } from 'react'
|
||||||
|
import { useRouter } from 'next/navigation'
|
||||||
import type { FC } from 'react'
|
import type { FC } from 'react'
|
||||||
import { useBoolean } from 'ahooks'
|
import { useBoolean } from 'ahooks'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
@ -41,9 +42,10 @@ const MCPDetailContent: FC<Props> = ({
|
|||||||
onHide,
|
onHide,
|
||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
const router = useRouter()
|
||||||
const { isCurrentWorkspaceManager } = useAppContext()
|
const { isCurrentWorkspaceManager } = useAppContext()
|
||||||
|
|
||||||
const { data, isPending: isGettingTools } = useMCPTools(detail.is_team_authorization ? detail.id : '')
|
const { data, isFetching: isGettingTools } = useMCPTools(detail.is_team_authorization ? detail.id : '')
|
||||||
const invalidateMCPTools = useInvalidateMCPTools()
|
const invalidateMCPTools = useInvalidateMCPTools()
|
||||||
const { mutateAsync: updateTools, isPending: isUpdating } = useUpdateMCPTools()
|
const { mutateAsync: updateTools, isPending: isUpdating } = useUpdateMCPTools()
|
||||||
const { mutateAsync: authorizeMcp, isPending: isAuthorizing } = useAuthorizeMCP()
|
const { mutateAsync: authorizeMcp, isPending: isAuthorizing } = useAuthorizeMCP()
|
||||||
@ -54,6 +56,7 @@ const MCPDetailContent: FC<Props> = ({
|
|||||||
return
|
return
|
||||||
await updateTools(detail.id)
|
await updateTools(detail.id)
|
||||||
invalidateMCPTools(detail.id)
|
invalidateMCPTools(detail.id)
|
||||||
|
onUpdate()
|
||||||
}, [detail, updateTools])
|
}, [detail, updateTools])
|
||||||
|
|
||||||
const { mutate: updateMCP } = useUpdateMCP({
|
const { mutate: updateMCP } = useUpdateMCP({
|
||||||
@ -85,11 +88,11 @@ const MCPDetailContent: FC<Props> = ({
|
|||||||
provider_id: detail.id,
|
provider_id: detail.id,
|
||||||
server_url: detail.server_url!,
|
server_url: detail.server_url!,
|
||||||
})
|
})
|
||||||
// TODO
|
if (res.result === 'success')
|
||||||
if ((res as any)?.result === 'success') {
|
handleUpdateTools()
|
||||||
hideUpdateModal()
|
|
||||||
onUpdate()
|
else if (res.authorization_url)
|
||||||
}
|
router.push(res.authorization_url)
|
||||||
}, [detail, updateMCP, hideUpdateModal, onUpdate])
|
}, [detail, updateMCP, hideUpdateModal, onUpdate])
|
||||||
|
|
||||||
const handleUpdate = useCallback(async (data: any) => {
|
const handleUpdate = useCallback(async (data: any) => {
|
||||||
@ -117,8 +120,6 @@ const MCPDetailContent: FC<Props> = ({
|
|||||||
}
|
}
|
||||||
}, [detail, showDeleting, hideDeleting, hideDeleteConfirm, onUpdate])
|
}, [detail, showDeleting, hideDeleting, hideDeleteConfirm, onUpdate])
|
||||||
|
|
||||||
const [loading, setLoading] = useState(false)
|
|
||||||
|
|
||||||
if (!detail)
|
if (!detail)
|
||||||
return null
|
return null
|
||||||
|
|
||||||
@ -150,7 +151,6 @@ const MCPDetailContent: FC<Props> = ({
|
|||||||
<Button
|
<Button
|
||||||
variant='secondary'
|
variant='secondary'
|
||||||
className='w-full'
|
className='w-full'
|
||||||
// onClick={() => setShowSettingAuth(true)}
|
|
||||||
disabled={!isCurrentWorkspaceManager}
|
disabled={!isCurrentWorkspaceManager}
|
||||||
>
|
>
|
||||||
<Indicator className='mr-2' color={'green'} />
|
<Indicator className='mr-2' color={'green'} />
|
||||||
|
@ -1,9 +1,16 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import { useMemo, useState } from 'react'
|
import { useEffect, useMemo, useState } from 'react'
|
||||||
|
import { useSearchParams } from 'next/navigation'
|
||||||
import NewMCPCard from './create-card'
|
import NewMCPCard from './create-card'
|
||||||
import MCPCard from './provider-card'
|
import MCPCard from './provider-card'
|
||||||
import MCPDetailPanel from './detail/provider-detail'
|
import MCPDetailPanel from './detail/provider-detail'
|
||||||
import { useAllMCPTools, useAuthorizeMCP, useInvalidateAllMCPTools, useInvalidateMCPTools, useUpdateMCPTools } from '@/service/use-tools'
|
import {
|
||||||
|
useAllMCPTools,
|
||||||
|
useAuthorizeMCP,
|
||||||
|
useInvalidateMCPTools,
|
||||||
|
useUpdateMCPAuthorizationToken,
|
||||||
|
useUpdateMCPTools,
|
||||||
|
} from '@/service/use-tools'
|
||||||
import type { ToolWithProvider } from '@/app/components/workflow/types'
|
import type { ToolWithProvider } from '@/app/components/workflow/types'
|
||||||
import cn from '@/utils/classnames'
|
import cn from '@/utils/classnames'
|
||||||
|
|
||||||
@ -32,11 +39,15 @@ function renderDefaultCard() {
|
|||||||
const MCPList = ({
|
const MCPList = ({
|
||||||
searchText,
|
searchText,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const { data: list = [] } = useAllMCPTools()
|
const searchParams = useSearchParams()
|
||||||
const invalidateMCPList = useInvalidateAllMCPTools()
|
const authCode = searchParams.get('code') || ''
|
||||||
|
const providerID = decodeURIComponent(searchParams.get('state') || '').split('provider_id=')[1] || ''
|
||||||
|
|
||||||
|
const { data: list = [], refetch } = useAllMCPTools()
|
||||||
const { mutateAsync: authorizeMcp } = useAuthorizeMCP()
|
const { mutateAsync: authorizeMcp } = useAuthorizeMCP()
|
||||||
const { mutateAsync: updateTools } = useUpdateMCPTools()
|
const { mutateAsync: updateTools } = useUpdateMCPTools()
|
||||||
const invalidateMCPTools = useInvalidateMCPTools()
|
const invalidateMCPTools = useInvalidateMCPTools()
|
||||||
|
const { mutateAsync: updateMCPAuthorizationToken } = useUpdateMCPAuthorizationToken()
|
||||||
|
|
||||||
const filteredList = useMemo(() => {
|
const filteredList = useMemo(() => {
|
||||||
return list.filter((collection) => {
|
return list.filter((collection) => {
|
||||||
@ -53,16 +64,38 @@ const MCPList = ({
|
|||||||
}, [list, currentProviderID])
|
}, [list, currentProviderID])
|
||||||
|
|
||||||
const handleCreate = async (provider: ToolWithProvider) => {
|
const handleCreate = async (provider: ToolWithProvider) => {
|
||||||
invalidateMCPList()
|
await refetch() // update list
|
||||||
setCurrentProviderID(provider.id)
|
setCurrentProviderID(provider.id)
|
||||||
await authorizeMcp({
|
await authorizeMcp({
|
||||||
provider_id: provider.id,
|
provider_id: provider.id,
|
||||||
server_url: provider.server_url!,
|
server_url: provider.server_url!,
|
||||||
})
|
})
|
||||||
|
await refetch() // update authorization in list
|
||||||
await updateTools(provider.id)
|
await updateTools(provider.id)
|
||||||
invalidateMCPTools(provider.id)
|
invalidateMCPTools(provider.id)
|
||||||
|
await refetch() // update tool list in provider list
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleUpdateAuthorization = async (providerID: string, code: string) => {
|
||||||
|
const targetProvider = list.find(provider => provider.id === providerID)
|
||||||
|
if (!targetProvider) return
|
||||||
|
await updateMCPAuthorizationToken({
|
||||||
|
provider_id: providerID,
|
||||||
|
server_url: targetProvider.server_url!,
|
||||||
|
authorization_code: code,
|
||||||
|
})
|
||||||
|
await refetch()
|
||||||
|
setCurrentProviderID(providerID)
|
||||||
|
await updateTools(providerID)
|
||||||
|
invalidateMCPTools(providerID)
|
||||||
|
await refetch()
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (authCode && providerID)
|
||||||
|
handleUpdateAuthorization(providerID, authCode)
|
||||||
|
}, [authCode, providerID])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div
|
<div
|
||||||
@ -78,7 +111,7 @@ const MCPList = ({
|
|||||||
data={provider}
|
data={provider}
|
||||||
currentProvider={currentProvider}
|
currentProvider={currentProvider}
|
||||||
handleSelect={setCurrentProviderID}
|
handleSelect={setCurrentProviderID}
|
||||||
onUpdate={() => invalidateMCPList()}
|
onUpdate={refetch}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
{!list.length && renderDefaultCard()}
|
{!list.length && renderDefaultCard()}
|
||||||
@ -87,7 +120,7 @@ const MCPList = ({
|
|||||||
<MCPDetailPanel
|
<MCPDetailPanel
|
||||||
detail={currentProvider}
|
detail={currentProvider}
|
||||||
onHide={() => setCurrentProviderID(undefined)}
|
onHide={() => setCurrentProviderID(undefined)}
|
||||||
onUpdate={() => invalidateMCPList()}
|
onUpdate={refetch}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import { useMemo, useRef, useState } from 'react'
|
import { useMemo, useRef, useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import { useSearchParams } from 'next/navigation'
|
||||||
import type { Collection } from './types'
|
import type { Collection } from './types'
|
||||||
import Marketplace from './marketplace'
|
import Marketplace from './marketplace'
|
||||||
import cn from '@/utils/classnames'
|
import cn from '@/utils/classnames'
|
||||||
@ -25,8 +26,12 @@ const ProviderList = () => {
|
|||||||
const containerRef = useRef<HTMLDivElement>(null)
|
const containerRef = useRef<HTMLDivElement>(null)
|
||||||
const { enable_marketplace } = useAppContextSelector(s => s.systemFeatures)
|
const { enable_marketplace } = useAppContextSelector(s => s.systemFeatures)
|
||||||
|
|
||||||
|
const searchParams = useSearchParams()
|
||||||
|
const authCode = searchParams.get('code') || ''
|
||||||
|
const providerID = decodeURIComponent(searchParams.get('state') || '').split('provider_id=')[1] || ''
|
||||||
|
|
||||||
const [activeTab, setActiveTab] = useTabSearchParams({
|
const [activeTab, setActiveTab] = useTabSearchParams({
|
||||||
defaultTab: 'builtin',
|
defaultTab: authCode && providerID ? 'mcp' : 'builtin',
|
||||||
})
|
})
|
||||||
const options = [
|
const options = [
|
||||||
{ value: 'builtin', text: t('tools.type.builtIn') },
|
{ value: 'builtin', text: t('tools.type.builtIn') },
|
||||||
|
@ -141,13 +141,26 @@ export const useAuthorizeMCP = () => {
|
|||||||
return useMutation({
|
return useMutation({
|
||||||
mutationKey: [NAME_SPACE, 'authorize-mcp'],
|
mutationKey: [NAME_SPACE, 'authorize-mcp'],
|
||||||
mutationFn: (payload: { provider_id: string; server_url: string }) => {
|
mutationFn: (payload: { provider_id: string; server_url: string }) => {
|
||||||
return post('/workspaces/current/tool-provider/mcp/auth', {
|
return post<{ result?: string; authorization_url?: string }>('/workspaces/current/tool-provider/mcp/auth', {
|
||||||
body: payload,
|
body: payload,
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const useUpdateMCPAuthorizationToken = () => {
|
||||||
|
return useMutation({
|
||||||
|
mutationKey: [NAME_SPACE, 'refresh-mcp-server-code'],
|
||||||
|
mutationFn: (payload: { provider_id: string; server_url: string; authorization_code: string }) => {
|
||||||
|
return get<MCPServerDetail>('/workspaces/current/tool-provider/mcp/token', {
|
||||||
|
params: {
|
||||||
|
...payload,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
export const useMCPTools = (providerID: string) => {
|
export const useMCPTools = (providerID: string) => {
|
||||||
return useQuery({
|
return useQuery({
|
||||||
enabled: !!providerID,
|
enabled: !!providerID,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user