Feature - add Teradata MCP server (#5002)
* added Teradata MCP server * fixed * fixed lint issue * updated latest teradata icon * Added TD Referance guide url * Fix module export by adding missing newline * Fix formatting of description in TeradataBearerToken --------- Co-authored-by: vj255006 <vilash.jagani@teradata.com> Co-authored-by: Henry Heng <henryheng@flowiseai.com>
This commit is contained in:
parent
b5da234ce7
commit
dd284e37c3
|
|
@ -0,0 +1,26 @@
|
|||
import { INodeParams, INodeCredential } from '../src/Interface'
|
||||
|
||||
class TeradataBearerTokenCredential implements INodeCredential {
|
||||
label: string
|
||||
name: string
|
||||
description: string
|
||||
version: number
|
||||
inputs: INodeParams[]
|
||||
|
||||
constructor() {
|
||||
this.label = 'Teradata Bearer Token'
|
||||
this.name = 'teradataBearerToken'
|
||||
this.version = 1.0
|
||||
this.description =
|
||||
'Refer to <a target="_blank" href="https://docs.teradata.com/r/Enterprise_IntelliFlex_VMware/Teradata-Vector-Store-User-Guide/Setting-up-Vector-Store/Importing-Modules-Required-for-Vector-Store">official guide</a> on how to get Teradata Bearer Token'
|
||||
this.inputs = [
|
||||
{
|
||||
label: 'Token',
|
||||
name: 'token',
|
||||
type: 'password'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { credClass: TeradataBearerTokenCredential }
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
import { INodeParams, INodeCredential } from '../src/Interface'
|
||||
|
||||
class TeradataTD2Credential implements INodeCredential {
|
||||
label: string
|
||||
name: string
|
||||
version: number
|
||||
inputs: INodeParams[]
|
||||
|
||||
constructor() {
|
||||
this.label = 'Teradata TD2 Auth'
|
||||
this.name = 'teradataTD2Auth'
|
||||
this.version = 1.0
|
||||
this.inputs = [
|
||||
{
|
||||
label: 'Teradata TD2 Auth Username',
|
||||
name: 'tdUsername',
|
||||
type: 'string'
|
||||
},
|
||||
{
|
||||
label: 'Teradata TD2 Auth Password',
|
||||
name: 'tdPassword',
|
||||
type: 'password'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { credClass: TeradataTD2Credential }
|
||||
|
|
@ -0,0 +1,147 @@
|
|||
import { Tool } from '@langchain/core/tools'
|
||||
import { ICommonObject, INode, INodeData, INodeOptionsValue, INodeParams } from '../../../../src/Interface'
|
||||
import { getCredentialData, getCredentialParam } from '../../../../src/utils'
|
||||
import { MCPToolkit } from '../core'
|
||||
import hash from 'object-hash'
|
||||
|
||||
class Teradata_MCP implements INode {
|
||||
label: string
|
||||
name: string
|
||||
version: number
|
||||
description: string
|
||||
type: string
|
||||
icon: string
|
||||
category: string
|
||||
baseClasses: string[]
|
||||
documentation: string
|
||||
credential: INodeParams
|
||||
inputs: INodeParams[]
|
||||
|
||||
constructor() {
|
||||
this.label = 'Teradata MCP'
|
||||
this.name = 'teradataMCP'
|
||||
this.version = 1.0
|
||||
this.type = 'Teradata MCP Tool'
|
||||
this.icon = 'teradata.svg'
|
||||
this.category = 'Tools (MCP)'
|
||||
this.description = 'MCP Server for Teradata (remote HTTP streamable)'
|
||||
this.documentation = 'https://github.com/Teradata/teradata-mcp-server'
|
||||
this.credential = {
|
||||
label: 'Connect Credential',
|
||||
name: 'credential',
|
||||
type: 'credential',
|
||||
credentialNames: ['teradataTD2Auth', 'teradataBearerToken'],
|
||||
description: 'Needed when using Teradata MCP server with authentication'
|
||||
}
|
||||
this.inputs = [
|
||||
{
|
||||
label: 'MCP Server URL',
|
||||
name: 'mcpUrl',
|
||||
type: 'string',
|
||||
placeholder: 'http://teradata-mcp-server:8001/mcp',
|
||||
description: 'URL of your Teradata MCP server',
|
||||
optional: false
|
||||
},
|
||||
{
|
||||
label: 'Bearer Token',
|
||||
name: 'bearerToken',
|
||||
type: 'string',
|
||||
optional: true,
|
||||
description: 'Optional to override Default set credentials'
|
||||
},
|
||||
{
|
||||
label: 'Available Actions',
|
||||
name: 'mcpActions',
|
||||
type: 'asyncMultiOptions',
|
||||
loadMethod: 'listActions',
|
||||
refresh: true
|
||||
}
|
||||
]
|
||||
this.baseClasses = ['Tool']
|
||||
}
|
||||
|
||||
//@ts-ignore
|
||||
loadMethods = {
|
||||
listActions: async (nodeData: INodeData, options: ICommonObject): Promise<INodeOptionsValue[]> => {
|
||||
try {
|
||||
const toolset = await this.getTools(nodeData, options)
|
||||
toolset.sort((a: any, b: any) => a.name.localeCompare(b.name))
|
||||
return toolset.map(({ name, ...rest }) => ({
|
||||
label: name.toUpperCase(),
|
||||
name: name,
|
||||
description: rest.description || name
|
||||
}))
|
||||
} catch (error) {
|
||||
console.error('Error listing actions:', error)
|
||||
return [
|
||||
{
|
||||
label: 'No Available Actions',
|
||||
name: 'error',
|
||||
description: 'No available actions, please check your MCP server URL and credentials, then refresh.'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async init(nodeData: INodeData, _: string, options: ICommonObject): Promise<any> {
|
||||
const tools = await this.getTools(nodeData, options)
|
||||
const _mcpActions = nodeData.inputs?.mcpActions
|
||||
let mcpActions = []
|
||||
if (_mcpActions) {
|
||||
try {
|
||||
mcpActions = typeof _mcpActions === 'string' ? JSON.parse(_mcpActions) : _mcpActions
|
||||
} catch (error) {
|
||||
console.error('Error parsing mcp actions:', error)
|
||||
}
|
||||
}
|
||||
return tools.filter((tool: any) => mcpActions.includes(tool.name))
|
||||
}
|
||||
|
||||
async getTools(nodeData: INodeData, options: ICommonObject): Promise<Tool[]> {
|
||||
const credentialData = await getCredentialData(nodeData.credential ?? '', options)
|
||||
const mcpUrl = nodeData.inputs?.mcpUrl || 'http://teradata-mcp-server:8001/mcp'
|
||||
if (!mcpUrl) {
|
||||
throw new Error('Missing MCP Server URL')
|
||||
}
|
||||
// Determine auth method from credentials
|
||||
let serverParams: any = {
|
||||
url: mcpUrl,
|
||||
headers: {}
|
||||
}
|
||||
// Get Bearer token from node input (from agent flow) or credential store
|
||||
const bearerToken = nodeData.inputs?.bearerToken || getCredentialParam('token', credentialData, nodeData)
|
||||
const username = getCredentialParam('tdUsername', credentialData, nodeData)
|
||||
const password = getCredentialParam('tdPassword', credentialData, nodeData)
|
||||
|
||||
if (bearerToken) {
|
||||
serverParams.headers['Authorization'] = `Bearer ${bearerToken}`
|
||||
} else if (username && password) {
|
||||
serverParams.headers['Authorization'] = 'Basic ' + Buffer.from(`${username}:${password}`).toString('base64')
|
||||
} else {
|
||||
throw new Error('Missing credentials: provide Bearer token from flow/credentials OR username/password from credentials')
|
||||
}
|
||||
const workspaceId = options?.searchOptions?.workspaceId?._value || options?.workspaceId || 'tdws_default'
|
||||
let sandbox: ICommonObject = {}
|
||||
const cacheKey = hash({ workspaceId, serverParams, sandbox })
|
||||
if (options.cachePool) {
|
||||
const cachedResult = await options.cachePool.getMCPCache(cacheKey)
|
||||
if (cachedResult) {
|
||||
if (cachedResult.tools.length > 0) {
|
||||
return cachedResult.tools
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Use SSE for remote HTTP MCP servers
|
||||
const toolkit = new MCPToolkit(serverParams, 'sse')
|
||||
await toolkit.initialize()
|
||||
const tools = toolkit.tools ?? []
|
||||
if (options.cachePool) {
|
||||
await options.cachePool.addMCPCache(cacheKey, { toolkit, tools })
|
||||
}
|
||||
return tools as Tool[]
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { nodeClass: Teradata_MCP }
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g filter="url(#filter0_d_15769_12621)">
|
||||
<path d="M49.3232 8H14.6768C13.1984 8 12 9.19843 12 10.6768V45.3232C12 46.8016 13.1984 48 14.6768 48H49.3232C50.8016 48 52 46.8016 52 45.3232V10.6768C52 9.19843 50.8016 8 49.3232 8Z" fill="#FF5F02"/>
|
||||
<path d="M25.098 32.467V15.5882H30.1292V20.2286H35.7465V24.6834H30.1292V32.467C30.1292 34.4794 31.1745 35.1364 32.6447 35.1364H35.7391V39.5863H32.6447C27.4915 39.5814 25.098 37.3369 25.098 32.467Z" fill="white"/>
|
||||
<path d="M37.8688 37.376C37.8688 36.668 38.1501 35.989 38.6507 35.4884C39.1513 34.9878 39.8303 34.7066 40.5383 34.7066C41.2462 34.7066 41.9252 34.9878 42.4258 35.4884C42.9265 35.989 43.2077 36.668 43.2077 37.376C43.2077 38.084 42.9265 38.7629 42.4258 39.2636C41.9252 39.7642 41.2462 40.0454 40.5383 40.0454C39.8303 40.0454 39.1513 39.7642 38.6507 39.2636C38.1501 38.7629 37.8688 38.084 37.8688 37.376Z" fill="white"/>
|
||||
</g>
|
||||
<defs>
|
||||
<filter id="filter0_d_15769_12621" x="0" y="0" width="64" height="64" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset dy="4"/>
|
||||
<feGaussianBlur stdDeviation="6"/>
|
||||
<feComposite in2="hardAlpha" operator="out"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.12 0"/>
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_15769_12621"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_15769_12621" result="shape"/>
|
||||
</filter>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
Loading…
Reference in New Issue