@ctera/n8n-nodes-ctera-ai 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +23 -0
- package/README.md +238 -0
- package/dist/credentials/CteraAiMcpApi.credentials.d.ts +7 -0
- package/dist/credentials/CteraAiMcpApi.credentials.js +42 -0
- package/dist/nodes/CteraAi/CteraAi.node.d.ts +5 -0
- package/dist/nodes/CteraAi/CteraAi.node.js +260 -0
- package/dist/nodes/CteraAi/ctera.svg +13 -0
- package/index.js +10 -0
- package/package.json +60 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 CTERA Networks
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
|
23
|
+
|
package/README.md
ADDED
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
# n8n-nodes-ctera-ai
|
|
2
|
+
|
|
3
|
+
This is an n8n community node that provides integration with CTERA AI MCP (Model Context Protocol) server for intelligent document search and retrieval.
|
|
4
|
+
|
|
5
|
+
[n8n](https://n8n.io/) is a [fair-code licensed](https://docs.n8n.io/reference/license/) workflow automation platform.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
### Community Installation (Recommended)
|
|
10
|
+
|
|
11
|
+
For n8n version 0.187.0 and above, you can install this node directly from npm:
|
|
12
|
+
|
|
13
|
+
#### Standard Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install -g @ctera/n8n-nodes-ctera-ai
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Then restart your n8n instance.
|
|
20
|
+
|
|
21
|
+
#### Docker Installation
|
|
22
|
+
|
|
23
|
+
For Docker-based n8n installations:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# Install the node inside the running container
|
|
27
|
+
docker exec -it <container-name> npm install -g @ctera/n8n-nodes-ctera-ai
|
|
28
|
+
|
|
29
|
+
# Restart the container
|
|
30
|
+
docker restart <container-name>
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Replace `<container-name>` with your actual container name (e.g., `n8n`, `n8n_n8n_1`).
|
|
34
|
+
|
|
35
|
+
**Note**: The node will persist across container restarts but will need to be reinstalled if the container is recreated. To make it permanent, consider creating a custom Docker image or using volume mounts.
|
|
36
|
+
|
|
37
|
+
### Manual Installation (Development)
|
|
38
|
+
|
|
39
|
+
1. Navigate to your n8n installation:
|
|
40
|
+
```bash
|
|
41
|
+
cd ~/.n8n/nodes
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
2. Clone the repository:
|
|
45
|
+
```bash
|
|
46
|
+
git clone https://github.com/ctera/ctera-n8n-nodes.git
|
|
47
|
+
cd ctera-n8n-nodes
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
3. Install dependencies and build:
|
|
51
|
+
```bash
|
|
52
|
+
npm install
|
|
53
|
+
npm run build
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
4. Restart n8n
|
|
57
|
+
|
|
58
|
+
For more details, see the [n8n community nodes installation guide](https://docs.n8n.io/integrations/community-nodes/installation/).
|
|
59
|
+
|
|
60
|
+
## Operations
|
|
61
|
+
|
|
62
|
+
The CTERA AI node supports the following operations:
|
|
63
|
+
|
|
64
|
+
### List Experts
|
|
65
|
+
Get a list of all available experts (AI knowledge bases) in the system.
|
|
66
|
+
|
|
67
|
+
**No parameters required**
|
|
68
|
+
|
|
69
|
+
**Output**: Array of expert objects containing:
|
|
70
|
+
- `id`: Expert ID for API calls
|
|
71
|
+
- `name`: Display name of the expert
|
|
72
|
+
- `description`: Brief description of the expert's knowledge domain
|
|
73
|
+
- `mcp_endpoint`: Dedicated MCP endpoint URL for this expert
|
|
74
|
+
|
|
75
|
+
### Semantic Search
|
|
76
|
+
Search an expert's knowledge base using advanced semantic search.
|
|
77
|
+
|
|
78
|
+
**Parameters**:
|
|
79
|
+
- **Expert** (required): Select from available experts (dropdown populated via List Experts)
|
|
80
|
+
- **Query** (required): Your search question or topic
|
|
81
|
+
- **Additional Options**:
|
|
82
|
+
- Modified After: Filter files modified on or after this date (YYYY-MM-DD)
|
|
83
|
+
- Modified Before: Filter files modified before this date (YYYY-MM-DD)
|
|
84
|
+
- Max Results: Number of relevant chunks to return (1-50, default: 5)
|
|
85
|
+
|
|
86
|
+
**Output**: Array of relevant document chunks with:
|
|
87
|
+
- Text content
|
|
88
|
+
- Source file paths
|
|
89
|
+
- Relevance scores
|
|
90
|
+
- Metadata (dates, file types, etc.)
|
|
91
|
+
|
|
92
|
+
### Chat
|
|
93
|
+
Have a conversational interaction with an AI expert about their knowledge domain.
|
|
94
|
+
|
|
95
|
+
**Parameters**:
|
|
96
|
+
- **Expert** (required): Select from available experts
|
|
97
|
+
- **Message** (required): Your message or question to the expert
|
|
98
|
+
- **Conversation ID** (optional): Continue an existing conversation thread
|
|
99
|
+
|
|
100
|
+
**Output**:
|
|
101
|
+
- AI expert's response
|
|
102
|
+
- Conversation ID (for follow-up messages)
|
|
103
|
+
- Citations to source documents (if applicable)
|
|
104
|
+
|
|
105
|
+
## Credentials
|
|
106
|
+
|
|
107
|
+
This node requires CTERA AI MCP API credentials:
|
|
108
|
+
|
|
109
|
+
### Setup Instructions
|
|
110
|
+
|
|
111
|
+
1. **Generate a Bearer Token**:
|
|
112
|
+
```bash
|
|
113
|
+
# Replace YOUR_MCP_SERVER, YOUR_OID, and email with your actual values
|
|
114
|
+
curl -k "https://YOUR_MCP_SERVER/api/tokens/generate?oid=YOUR_OID&email=your.email@example.com" | jq -r .token
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
2. **Add Credentials in n8n**:
|
|
118
|
+
- Go to **Credentials** → **New Credential**
|
|
119
|
+
- Search for "CTERA AI MCP API"
|
|
120
|
+
- Fill in:
|
|
121
|
+
- **MCP Server URL**: Your MCP server base URL (e.g., `https://mcp.example.com`)
|
|
122
|
+
- **Bearer Token**: Paste the token from step 1
|
|
123
|
+
- **Ignore SSL Issues**: Enable if using self-signed certificates
|
|
124
|
+
|
|
125
|
+
3. **Test the Credentials**: Click "Test" to verify connection
|
|
126
|
+
|
|
127
|
+
## Example Workflows
|
|
128
|
+
|
|
129
|
+
### Competitive Intelligence Daily Report
|
|
130
|
+
|
|
131
|
+
```
|
|
132
|
+
Schedule Trigger (Daily 9 AM)
|
|
133
|
+
↓
|
|
134
|
+
CTERA AI: List Experts
|
|
135
|
+
↓
|
|
136
|
+
Split In Batches
|
|
137
|
+
↓
|
|
138
|
+
CTERA AI: Semantic Search
|
|
139
|
+
- Expert: {{$json.id}}
|
|
140
|
+
- Query: "Recent updates, announcements, and new features"
|
|
141
|
+
- Modified After: {{$today.minus(7, 'days')}}
|
|
142
|
+
↓
|
|
143
|
+
Aggregate Results
|
|
144
|
+
↓
|
|
145
|
+
Send Email: Daily Intelligence Summary
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Interactive Q&A Chatbot
|
|
149
|
+
|
|
150
|
+
```
|
|
151
|
+
Webhook (Receive Question)
|
|
152
|
+
↓
|
|
153
|
+
CTERA AI: Chat
|
|
154
|
+
- Expert: (pre-configured expert ID)
|
|
155
|
+
- Message: {{$json.question}}
|
|
156
|
+
- Conversation ID: {{$json.conversationId}}
|
|
157
|
+
↓
|
|
158
|
+
Format Response
|
|
159
|
+
↓
|
|
160
|
+
Return Webhook Response
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### Document Discovery Workflow
|
|
164
|
+
|
|
165
|
+
```
|
|
166
|
+
Schedule Trigger (Hourly)
|
|
167
|
+
↓
|
|
168
|
+
CTERA AI: Semantic Search
|
|
169
|
+
- Expert: "Product Documentation"
|
|
170
|
+
- Query: "Installation and setup guides"
|
|
171
|
+
- Modified After: {{$today.minus(1, 'hour')}}
|
|
172
|
+
↓
|
|
173
|
+
Filter: If results not empty
|
|
174
|
+
↓
|
|
175
|
+
Send Slack Notification
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Compatibility
|
|
179
|
+
|
|
180
|
+
Tested with:
|
|
181
|
+
- n8n version: 1.0.0+
|
|
182
|
+
- CTERA AI MCP Server: 1.6.16+
|
|
183
|
+
|
|
184
|
+
## Resources
|
|
185
|
+
|
|
186
|
+
* [n8n community nodes documentation](https://docs.n8n.io/integrations/community-nodes/)
|
|
187
|
+
* [CTERA AI MCP Architecture](https://cteranet.atlassian.net/wiki/spaces/AI/pages/4757454995)
|
|
188
|
+
* [Model Context Protocol](https://modelcontextprotocol.io/)
|
|
189
|
+
|
|
190
|
+
## Development
|
|
191
|
+
|
|
192
|
+
### Build
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
npm run build
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Watch Mode
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
npm run dev
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### Linting
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
npm run lint
|
|
208
|
+
npm run lintfix
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Publishing
|
|
212
|
+
|
|
213
|
+
For maintainers publishing new versions to npm, see [PUBLISH.md](PUBLISH.md) for detailed instructions.
|
|
214
|
+
|
|
215
|
+
## Version History
|
|
216
|
+
|
|
217
|
+
### 0.1.0
|
|
218
|
+
- Initial public release
|
|
219
|
+
- List Experts operation
|
|
220
|
+
- Semantic Search operation
|
|
221
|
+
- Chat with Expert operation
|
|
222
|
+
- Bearer token authentication
|
|
223
|
+
|
|
224
|
+
## License
|
|
225
|
+
|
|
226
|
+
[MIT](LICENSE)
|
|
227
|
+
|
|
228
|
+
## Support
|
|
229
|
+
|
|
230
|
+
For issues and questions:
|
|
231
|
+
- GitHub Issues: https://github.com/ctera/ctera-n8n-nodes/issues
|
|
232
|
+
- CTERA Support: support@ctera.com
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CteraAiMcpApi = void 0;
|
|
4
|
+
class CteraAiMcpApi {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.name = 'cteraAiMcpApi';
|
|
7
|
+
this.displayName = 'CTERA AI MCP API';
|
|
8
|
+
this.documentationUrl = 'https://cteranet.atlassian.net/wiki/spaces/AI/pages/4757454995';
|
|
9
|
+
this.properties = [
|
|
10
|
+
{
|
|
11
|
+
displayName: 'MCP Server URL',
|
|
12
|
+
name: 'serverUrl',
|
|
13
|
+
type: 'string',
|
|
14
|
+
default: '',
|
|
15
|
+
required: true,
|
|
16
|
+
placeholder: 'https://mcp.your-domain.com',
|
|
17
|
+
description: 'The base URL of your CTERA AI MCP server (e.g., https://mcp.example.com)',
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
displayName: 'Bearer Token',
|
|
21
|
+
name: 'bearerToken',
|
|
22
|
+
type: 'string',
|
|
23
|
+
typeOptions: {
|
|
24
|
+
password: true,
|
|
25
|
+
},
|
|
26
|
+
default: '',
|
|
27
|
+
required: true,
|
|
28
|
+
description: 'Bearer token for authentication. Generate using: curl -k "https://<your-instance>/api/tokens/generate?oid=<your-oid>&email=<your-email>"',
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
displayName: 'Ignore SSL Issues',
|
|
32
|
+
name: 'allowUnauthorizedCerts',
|
|
33
|
+
type: 'boolean',
|
|
34
|
+
default: true,
|
|
35
|
+
description: 'Whether to connect even if SSL certificate validation is not possible',
|
|
36
|
+
},
|
|
37
|
+
];
|
|
38
|
+
// Note: Test is not included here since each node provides its own expert endpoint URL
|
|
39
|
+
// The node will test the connection when executing
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
exports.CteraAiMcpApi = CteraAiMcpApi;
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CteraAi = void 0;
|
|
4
|
+
const n8n_workflow_1 = require("n8n-workflow");
|
|
5
|
+
class CteraAi {
|
|
6
|
+
constructor() {
|
|
7
|
+
this.description = {
|
|
8
|
+
displayName: 'CTERA Data Intelligence',
|
|
9
|
+
name: 'cteraAi',
|
|
10
|
+
icon: 'file:ctera.svg',
|
|
11
|
+
group: ['transform'],
|
|
12
|
+
version: 1,
|
|
13
|
+
subtitle: '={{$parameter["tool"]}}',
|
|
14
|
+
description: 'Interact with CTERA Data Intelligence experts via per-expert MCP endpoints',
|
|
15
|
+
defaults: {
|
|
16
|
+
name: 'CTERA Data Intelligence',
|
|
17
|
+
},
|
|
18
|
+
inputs: ['main'],
|
|
19
|
+
outputs: ['main'],
|
|
20
|
+
credentials: [
|
|
21
|
+
{
|
|
22
|
+
name: 'cteraAiMcpApi',
|
|
23
|
+
required: true,
|
|
24
|
+
},
|
|
25
|
+
],
|
|
26
|
+
properties: [
|
|
27
|
+
{
|
|
28
|
+
displayName: 'Expert MCP Endpoint URL',
|
|
29
|
+
name: 'expertEndpointUrl',
|
|
30
|
+
type: 'string',
|
|
31
|
+
default: '',
|
|
32
|
+
required: true,
|
|
33
|
+
displayOptions: {
|
|
34
|
+
hide: {
|
|
35
|
+
operation: ['listExperts'],
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
placeholder: 'https://mcp.your-domain.com/mcp/experts/EXPERT_ID',
|
|
39
|
+
description: 'The per-expert MCP endpoint URL. Use "List Experts" operation to get this URL.',
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
displayName: 'Operation',
|
|
43
|
+
name: 'operation',
|
|
44
|
+
type: 'options',
|
|
45
|
+
options: [
|
|
46
|
+
{
|
|
47
|
+
name: 'List Experts',
|
|
48
|
+
value: 'listExperts',
|
|
49
|
+
description: 'Get list of all available experts',
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
name: 'Semantic Search (for RAG)',
|
|
53
|
+
value: 'search',
|
|
54
|
+
description: 'Retrieve raw text chunks for Retrieval-Augmented Generation',
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
name: 'Chat (Generative Answer)',
|
|
58
|
+
value: 'chat',
|
|
59
|
+
description: 'Get a direct, generated answer from the expert',
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
default: 'search',
|
|
63
|
+
required: true,
|
|
64
|
+
description: 'Choose the operation to perform',
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
displayName: 'Query',
|
|
68
|
+
name: 'query',
|
|
69
|
+
type: 'string',
|
|
70
|
+
default: '',
|
|
71
|
+
required: true,
|
|
72
|
+
displayOptions: {
|
|
73
|
+
hide: {
|
|
74
|
+
operation: ['listExperts'],
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
placeholder: 'What are the key features of the product?',
|
|
78
|
+
description: 'The natural language question to ask your data',
|
|
79
|
+
typeOptions: {
|
|
80
|
+
rows: 4,
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
displayName: 'Additional Options',
|
|
85
|
+
name: 'additionalOptions',
|
|
86
|
+
type: 'collection',
|
|
87
|
+
placeholder: 'Add Option',
|
|
88
|
+
default: {},
|
|
89
|
+
displayOptions: {
|
|
90
|
+
show: {
|
|
91
|
+
operation: ['search'],
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
options: [
|
|
95
|
+
{
|
|
96
|
+
displayName: 'Modified Date Start',
|
|
97
|
+
name: 'modified_date_start',
|
|
98
|
+
type: 'dateTime',
|
|
99
|
+
default: '',
|
|
100
|
+
description: 'Filter results from files modified on or after this date',
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
displayName: 'Modified Date End',
|
|
104
|
+
name: 'modified_date_end',
|
|
105
|
+
type: 'dateTime',
|
|
106
|
+
default: '',
|
|
107
|
+
description: 'Filter results from files modified up to this date',
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
displayName: 'Number of Results (k)',
|
|
111
|
+
name: 'k',
|
|
112
|
+
type: 'number',
|
|
113
|
+
default: 5,
|
|
114
|
+
description: 'Number of text chunks to fetch (top-k)',
|
|
115
|
+
typeOptions: {
|
|
116
|
+
minValue: 1,
|
|
117
|
+
maxValue: 50,
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
displayName: 'Window Size',
|
|
122
|
+
name: 'window_size',
|
|
123
|
+
type: 'number',
|
|
124
|
+
default: 2,
|
|
125
|
+
description: 'Context window size around matches (in KB)',
|
|
126
|
+
typeOptions: {
|
|
127
|
+
minValue: 1,
|
|
128
|
+
maxValue: 10,
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
],
|
|
132
|
+
},
|
|
133
|
+
],
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
async execute() {
|
|
137
|
+
const items = this.getInputData();
|
|
138
|
+
const returnData = [];
|
|
139
|
+
const credentials = await this.getCredentials('cteraAiMcpApi');
|
|
140
|
+
const bearerToken = credentials.bearerToken;
|
|
141
|
+
const allowUnauthorizedCerts = credentials.allowUnauthorizedCerts;
|
|
142
|
+
const mcpServerUrl = credentials.serverUrl.replace(/\/$/, ''); // Remove trailing slash
|
|
143
|
+
for (let i = 0; i < items.length; i++) {
|
|
144
|
+
try {
|
|
145
|
+
const operation = this.getNodeParameter('operation', i);
|
|
146
|
+
let toolName;
|
|
147
|
+
let serverUrl;
|
|
148
|
+
const params = {};
|
|
149
|
+
// Determine tool name, server URL, and parameters based on operation
|
|
150
|
+
if (operation === 'listExperts') {
|
|
151
|
+
toolName = 'ctera_list_experts';
|
|
152
|
+
serverUrl = `${mcpServerUrl}/mcp-bearer`;
|
|
153
|
+
// No parameters needed
|
|
154
|
+
}
|
|
155
|
+
else if (operation === 'search') {
|
|
156
|
+
toolName = 'expert_semantic_search';
|
|
157
|
+
serverUrl = this.getNodeParameter('expertEndpointUrl', i);
|
|
158
|
+
const query = this.getNodeParameter('query', i);
|
|
159
|
+
const additionalOptions = this.getNodeParameter('additionalOptions', i, {});
|
|
160
|
+
params.query = query;
|
|
161
|
+
if (additionalOptions.modified_date_start) {
|
|
162
|
+
params.modified_date_start = new Date(additionalOptions.modified_date_start).toISOString();
|
|
163
|
+
}
|
|
164
|
+
if (additionalOptions.modified_date_end) {
|
|
165
|
+
params.modified_date_end = new Date(additionalOptions.modified_date_end).toISOString();
|
|
166
|
+
}
|
|
167
|
+
if (additionalOptions.k) {
|
|
168
|
+
params.k = additionalOptions.k;
|
|
169
|
+
}
|
|
170
|
+
if (additionalOptions.window_size) {
|
|
171
|
+
params.window_size = additionalOptions.window_size;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
else if (operation === 'chat') {
|
|
175
|
+
toolName = 'expert_chat';
|
|
176
|
+
serverUrl = this.getNodeParameter('expertEndpointUrl', i);
|
|
177
|
+
const query = this.getNodeParameter('query', i);
|
|
178
|
+
params.message = query;
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Unknown operation: ${operation}`, {
|
|
182
|
+
itemIndex: i,
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
// Construct the JSON-RPC payload
|
|
186
|
+
const requestBody = {
|
|
187
|
+
jsonrpc: '2.0',
|
|
188
|
+
method: 'tools/call',
|
|
189
|
+
params: {
|
|
190
|
+
name: toolName,
|
|
191
|
+
arguments: params,
|
|
192
|
+
},
|
|
193
|
+
id: i + 1,
|
|
194
|
+
};
|
|
195
|
+
// Make the HTTP request
|
|
196
|
+
const response = await this.helpers.httpRequest({
|
|
197
|
+
method: 'POST',
|
|
198
|
+
url: serverUrl,
|
|
199
|
+
headers: {
|
|
200
|
+
'Content-Type': 'application/json',
|
|
201
|
+
'Authorization': `Bearer ${bearerToken}`,
|
|
202
|
+
},
|
|
203
|
+
body: requestBody,
|
|
204
|
+
json: true,
|
|
205
|
+
skipSslCertificateValidation: allowUnauthorizedCerts,
|
|
206
|
+
});
|
|
207
|
+
// Handle MCP error responses
|
|
208
|
+
if (response.error) {
|
|
209
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `MCP Error: ${response.error.message || JSON.stringify(response.error)}`, { itemIndex: i });
|
|
210
|
+
}
|
|
211
|
+
// Parse the result from MCP response
|
|
212
|
+
let result;
|
|
213
|
+
if (response.result && response.result.content) {
|
|
214
|
+
// MCP returns content array
|
|
215
|
+
const content = response.result.content[0];
|
|
216
|
+
if (content && content.type === 'text') {
|
|
217
|
+
try {
|
|
218
|
+
// Try to parse as JSON if it looks like JSON
|
|
219
|
+
result = JSON.parse(content.text);
|
|
220
|
+
}
|
|
221
|
+
catch {
|
|
222
|
+
// If not JSON, return as text
|
|
223
|
+
result = content.text;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
result = content;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
else {
|
|
231
|
+
result = response.result;
|
|
232
|
+
}
|
|
233
|
+
returnData.push({
|
|
234
|
+
json: {
|
|
235
|
+
operation,
|
|
236
|
+
toolName,
|
|
237
|
+
result,
|
|
238
|
+
...items[i].json,
|
|
239
|
+
},
|
|
240
|
+
pairedItem: { item: i },
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
catch (error) {
|
|
244
|
+
if (this.continueOnFail()) {
|
|
245
|
+
returnData.push({
|
|
246
|
+
json: {
|
|
247
|
+
error: error.message,
|
|
248
|
+
...items[i].json,
|
|
249
|
+
},
|
|
250
|
+
pairedItem: { item: i },
|
|
251
|
+
});
|
|
252
|
+
continue;
|
|
253
|
+
}
|
|
254
|
+
throw error;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
return [returnData];
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
exports.CteraAi = CteraAi;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<g clip-path="url(#ub91fxv4ea)" transform="scale(1.15) translate(-1.8, -1.8)">
|
|
3
|
+
<path d="M20 0H4a4 4 0 0 0-4 4v16a4 4 0 0 0 4 4h16a4 4 0 0 0 4-4V4a4 4 0 0 0-4-4z" fill="#4F5CE5"/>
|
|
4
|
+
<path d="M20.373 15.297a8.941 8.941 0 0 1-2.01 3.066A8.98 8.98 0 0 1 12 21a8.883 8.883 0 0 1-3.297-.627 8.942 8.942 0 0 1-3.066-2.01A8.981 8.981 0 0 1 3 12c0-1.163.22-2.277.627-3.297a8.943 8.943 0 0 1 2.01-3.066A8.982 8.982 0 0 1 12 3c1.163 0 2.277.22 3.297.627a8.943 8.943 0 0 1 3.066 2.01l-1.65 1.65A6.668 6.668 0 0 0 12 5.333a6.663 6.663 0 0 0-4.713 1.953A6.668 6.668 0 0 0 5.333 12a6.664 6.664 0 0 0 1.953 4.713A6.668 6.668 0 0 0 12 18.667a6.662 6.662 0 0 0 4.713-1.953 6.667 6.667 0 0 0 1.49-2.27l2.17.853z" fill="#fff" stroke="#4F5CE5" stroke-width=".667" stroke-miterlimit="10"/>
|
|
5
|
+
<path d="M18.203 14.443a6.668 6.668 0 0 1-3.543 3.67 6.608 6.608 0 0 1-2.66.554 6.669 6.669 0 0 1-6.113-4.007A6.607 6.607 0 0 1 5.333 12 6.668 6.668 0 0 1 9.34 5.887 6.607 6.607 0 0 1 12 5.333a6.667 6.667 0 0 1 4.713 1.953L14.71 9.29A3.818 3.818 0 0 0 12 8.167c-.543 0-1.06.113-1.53.316A3.85 3.85 0 0 0 8.167 12c0 .543.113 1.06.316 1.53a3.847 3.847 0 0 0 5.047 1.987 3.848 3.848 0 0 0 2.037-2.114l2.636 1.04z" fill="#fff" stroke="#4F5CE5" stroke-width=".667" stroke-miterlimit="10"/>
|
|
6
|
+
<path d="M13.874 12c0 .13-.08.247-.204.292l-1.006.372-.37 1.007a.31.31 0 0 1-.584 0l-.373-1.007-1.007-.371a.31.31 0 0 1 0-.583l1.007-.373.37-1.008a.31.31 0 0 1 .584 0l.373 1.008 1.007.37a.308.308 0 0 1 .203.293z" fill="#fff"/>
|
|
7
|
+
</g>
|
|
8
|
+
<defs>
|
|
9
|
+
<clipPath id="ub91fxv4ea">
|
|
10
|
+
<path fill="#fff" d="M0 0h24v24H0z"/>
|
|
11
|
+
</clipPath>
|
|
12
|
+
</defs>
|
|
13
|
+
</svg>
|
package/index.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ctera/n8n-nodes-ctera-ai",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "n8n community node for CTERA AI MCP integration - enables semantic search, chat, and expert discovery",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"n8n-community-node-package",
|
|
7
|
+
"n8n",
|
|
8
|
+
"ctera",
|
|
9
|
+
"ai",
|
|
10
|
+
"mcp",
|
|
11
|
+
"rag"
|
|
12
|
+
],
|
|
13
|
+
"license": "MIT",
|
|
14
|
+
"homepage": "https://github.com/ctera/ctera-n8n-nodes",
|
|
15
|
+
"author": {
|
|
16
|
+
"name": "CTERA Networks",
|
|
17
|
+
"email": "support@ctera.com"
|
|
18
|
+
},
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "https://github.com/ctera/ctera-n8n-nodes.git"
|
|
22
|
+
},
|
|
23
|
+
"publishConfig": {
|
|
24
|
+
"access": "public"
|
|
25
|
+
},
|
|
26
|
+
"main": "index.js",
|
|
27
|
+
"scripts": {
|
|
28
|
+
"build": "tsc && gulp build:icons",
|
|
29
|
+
"dev": "tsc --watch",
|
|
30
|
+
"format": "prettier nodes credentials --write",
|
|
31
|
+
"lint": "eslint 'nodes/**/*.ts' 'credentials/**/*.ts' package.json",
|
|
32
|
+
"lintfix": "eslint 'nodes/**/*.ts' 'credentials/**/*.ts' package.json --fix",
|
|
33
|
+
"prepublishOnly": "npm run build && npm run lint"
|
|
34
|
+
},
|
|
35
|
+
"files": [
|
|
36
|
+
"dist"
|
|
37
|
+
],
|
|
38
|
+
"n8n": {
|
|
39
|
+
"n8nNodesApiVersion": 1,
|
|
40
|
+
"credentials": [
|
|
41
|
+
"dist/credentials/CteraAiMcpApi.credentials.js"
|
|
42
|
+
],
|
|
43
|
+
"nodes": [
|
|
44
|
+
"dist/nodes/CteraAi/CteraAi.node.js"
|
|
45
|
+
]
|
|
46
|
+
},
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"@typescript-eslint/eslint-plugin": "^5.62.0",
|
|
49
|
+
"@typescript-eslint/parser": "^5.59.0",
|
|
50
|
+
"eslint": "^8.40.0",
|
|
51
|
+
"eslint-plugin-n8n-nodes-base": "^1.12.0",
|
|
52
|
+
"gulp": "^5.0.1",
|
|
53
|
+
"n8n-workflow": "^1.0.0",
|
|
54
|
+
"prettier": "^2.8.8",
|
|
55
|
+
"typescript": "^5.0.4"
|
|
56
|
+
},
|
|
57
|
+
"peerDependencies": {
|
|
58
|
+
"n8n-workflow": "^1.0.0"
|
|
59
|
+
}
|
|
60
|
+
}
|