parent
cf7d841f88
commit
ac7cf30e01
|
|
@ -0,0 +1,129 @@
|
|||
import { Tool } from '@langchain/core/tools'
|
||||
import { INode, INodeData, INodeOptionsValue, INodeParams } from '../../../../src/Interface'
|
||||
import { MCPToolkit } from '../core'
|
||||
|
||||
const mcpServerConfig = `{
|
||||
"command": "npx",
|
||||
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/allowed/files"]
|
||||
}`
|
||||
|
||||
class Custom_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 = 'Custom MCP'
|
||||
this.name = 'customMCP'
|
||||
this.version = 1.0
|
||||
this.type = 'Custom MCP Tool'
|
||||
this.icon = 'customMCP.png'
|
||||
this.category = 'Tools (MCP)'
|
||||
this.description = 'Custom MCP Config'
|
||||
this.documentation = 'https://github.com/modelcontextprotocol/servers/tree/main/src/brave-search'
|
||||
this.inputs = [
|
||||
{
|
||||
label: 'MCP Server Config',
|
||||
name: 'mcpServerConfig',
|
||||
type: 'code',
|
||||
hideCodeExecute: true,
|
||||
placeholder: mcpServerConfig
|
||||
},
|
||||
{
|
||||
label: 'Available Actions',
|
||||
name: 'mcpActions',
|
||||
type: 'asyncMultiOptions',
|
||||
loadMethod: 'listActions',
|
||||
refresh: true
|
||||
}
|
||||
]
|
||||
this.baseClasses = ['Tool']
|
||||
}
|
||||
|
||||
//@ts-ignore
|
||||
loadMethods = {
|
||||
listActions: async (nodeData: INodeData): Promise<INodeOptionsValue[]> => {
|
||||
try {
|
||||
const toolset = await this.getTools(nodeData)
|
||||
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) {
|
||||
return [
|
||||
{
|
||||
label: 'No Available Actions',
|
||||
name: 'error',
|
||||
description: 'No available actions, please check your API key and refresh'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async init(nodeData: INodeData): Promise<any> {
|
||||
const tools = await this.getTools(nodeData)
|
||||
|
||||
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): Promise<Tool[]> {
|
||||
const mcpServerConfig = nodeData.inputs?.mcpServerConfig as string
|
||||
|
||||
if (!mcpServerConfig) {
|
||||
throw new Error('MCP Server Config is required')
|
||||
}
|
||||
|
||||
try {
|
||||
let serverParams
|
||||
if (typeof mcpServerConfig === 'object') {
|
||||
serverParams = mcpServerConfig
|
||||
} else if (typeof mcpServerConfig === 'string') {
|
||||
const serverParamsString = convertToValidJSONString(mcpServerConfig)
|
||||
serverParams = JSON.parse(serverParamsString)
|
||||
}
|
||||
|
||||
const toolkit = new MCPToolkit(serverParams, 'stdio')
|
||||
await toolkit.initialize()
|
||||
|
||||
const tools = toolkit.tools ?? []
|
||||
|
||||
return tools as Tool[]
|
||||
} catch (error) {
|
||||
throw new Error(`Invalid MCP Server Config: ${error}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function convertToValidJSONString(inputString: string) {
|
||||
try {
|
||||
const jsObject = Function('return ' + inputString)()
|
||||
return JSON.stringify(jsObject, null, 2)
|
||||
} catch (error) {
|
||||
console.error('Error converting to JSON:', error)
|
||||
return ''
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { nodeClass: Custom_MCP }
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 4.0 KiB |
|
|
@ -15,14 +15,14 @@ export class MCPToolkit extends BaseToolkit {
|
|||
if (transport === 'stdio') {
|
||||
this.transport = new StdioClientTransport(serverParams as StdioServerParameters)
|
||||
} else {
|
||||
//this.transport = new SSEClientTransport(serverParams.url);
|
||||
// TODO: this.transport = new SSEClientTransport(serverParams.url);
|
||||
}
|
||||
}
|
||||
async initialize() {
|
||||
if (this._tools === null) {
|
||||
this.client = new Client(
|
||||
{
|
||||
name: 'langchain-js-client',
|
||||
name: 'flowise-client',
|
||||
version: '1.0.0'
|
||||
},
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue