117 lines
3.8 KiB
TypeScript
117 lines
3.8 KiB
TypeScript
import { Tool } from '@langchain/core/tools'
|
|
import { ICommonObject, INode, INodeData, INodeOptionsValue, INodeParams } from '../../../../src/Interface'
|
|
import { getCredentialData, getCredentialParam, getNodeModulesPackagePath } from '../../../../src/utils'
|
|
import { MCPToolkit } from '../core'
|
|
|
|
class Slack_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 = 'Slack MCP'
|
|
this.name = 'slackMCP'
|
|
this.version = 1.0
|
|
this.type = 'Slack MCP Tool'
|
|
this.icon = 'slack.svg'
|
|
this.category = 'Tools (MCP)'
|
|
this.description = 'MCP Server for the Slack API'
|
|
this.documentation = 'https://github.com/modelcontextprotocol/servers/tree/main/src/slack'
|
|
this.credential = {
|
|
label: 'Connect Credential',
|
|
name: 'credential',
|
|
type: 'credential',
|
|
credentialNames: ['slackApi']
|
|
}
|
|
this.inputs = [
|
|
{
|
|
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 Slack Bot Token and 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 botToken = getCredentialParam('botToken', credentialData, nodeData)
|
|
const teamId = getCredentialParam('teamId', credentialData, nodeData)
|
|
|
|
if (!botToken || !teamId) {
|
|
throw new Error('Missing Credentials')
|
|
}
|
|
|
|
const packagePath = getNodeModulesPackagePath('@modelcontextprotocol/server-slack/dist/index.js')
|
|
|
|
const serverParams = {
|
|
command: 'node',
|
|
args: [packagePath],
|
|
env: {
|
|
SLACK_BOT_TOKEN: botToken,
|
|
SLACK_TEAM_ID: teamId
|
|
}
|
|
}
|
|
|
|
const toolkit = new MCPToolkit(serverParams, 'stdio')
|
|
await toolkit.initialize()
|
|
|
|
const tools = toolkit.tools ?? []
|
|
|
|
return tools as Tool[]
|
|
}
|
|
}
|
|
|
|
module.exports = { nodeClass: Slack_MCP }
|