feat: support dynamic MCP tool loading
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
import { mkdtemp, rm } from 'node:fs/promises'
|
||||
import { tmpdir } from 'node:os'
|
||||
import { join } from 'node:path'
|
||||
import { afterEach, expect, it } from 'vitest'
|
||||
import type { ResolvedMcpServer } from '../capabilities/capability-service'
|
||||
import { ModelToolProvider } from './model-tool-provider'
|
||||
|
||||
const temporaryDirectories: string[] = []
|
||||
const crmToken = process.env.GOODBUDDY_TEST_CRM_MCP_TOKEN?.trim()
|
||||
const externalTest = crmToken ? it : it.skip
|
||||
|
||||
afterEach(async () => {
|
||||
await Promise.all(
|
||||
temporaryDirectories
|
||||
.splice(0)
|
||||
.map((directory) =>
|
||||
rm(directory, { recursive: true, force: true })
|
||||
)
|
||||
)
|
||||
})
|
||||
|
||||
externalTest(
|
||||
'refreshes tools from a real dynamic MCP server',
|
||||
async () => {
|
||||
const workspace = await mkdtemp(
|
||||
join(tmpdir(), 'goodbuddy-dynamic-mcp-')
|
||||
)
|
||||
temporaryDirectories.push(workspace)
|
||||
const server: ResolvedMcpServer = {
|
||||
id: '00000000-0000-4000-8000-000000000401',
|
||||
name: 'CRM',
|
||||
description: '',
|
||||
enabled: true,
|
||||
allowDynamicTools: true,
|
||||
assignments: ['model'],
|
||||
secretConfigured: true,
|
||||
secret: crmToken,
|
||||
transport: 'http',
|
||||
url: 'https://crm.digiman.live/mcp'
|
||||
}
|
||||
const provider = new ModelToolProvider(workspace, [server])
|
||||
const signal = new AbortController().signal
|
||||
const context = {
|
||||
conversationId: 'dynamic-mcp-integration',
|
||||
workMode: 'execute'
|
||||
} as const
|
||||
|
||||
try {
|
||||
const initialTools = await provider.listTools(context, signal)
|
||||
const loadTool = initialTools.find(
|
||||
(tool) =>
|
||||
tool.displayName === 'CRM / crmtools_load_tools'
|
||||
)
|
||||
expect(loadTool).toBeDefined()
|
||||
|
||||
await provider.callTool(
|
||||
loadTool?.name ?? '',
|
||||
{ groups: ['opportunity'] },
|
||||
signal,
|
||||
context
|
||||
)
|
||||
|
||||
const refreshedTools = await provider.listTools(context, signal)
|
||||
expect(refreshedTools).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
displayName: 'CRM / crmtools_list_opportunities'
|
||||
})
|
||||
])
|
||||
)
|
||||
} finally {
|
||||
await provider.dispose()
|
||||
}
|
||||
},
|
||||
20_000
|
||||
)
|
||||
Reference in New Issue
Block a user