flowmind 1.0.1 → 1.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/README_CN.md +248 -0
- package/bin/flowmind.js +184 -2
- package/config/ai-config.example.json +64 -0
- package/config/claude-mcp-config.example.json +12 -0
- package/core/ai/base-model.js +70 -0
- package/core/ai/index.js +29 -0
- package/core/ai/model-manager.js +320 -0
- package/core/ai/prompts/extraction.js +38 -0
- package/core/ai/prompts/index.js +11 -0
- package/core/ai/prompts/intent.js +43 -0
- package/core/ai/prompts/learning.js +46 -0
- package/core/ai/prompts/selection.js +38 -0
- package/core/ai/prompts/summary.js +35 -0
- package/core/ai/providers/anthropic.js +93 -0
- package/core/ai/providers/deepseek.js +80 -0
- package/core/ai/providers/ernie.js +111 -0
- package/core/ai/providers/glm.js +80 -0
- package/core/ai/providers/mimo.js +80 -0
- package/core/ai/providers/ollama.js +147 -0
- package/core/ai/providers/openai.js +82 -0
- package/core/ai/providers/qwen.js +80 -0
- package/core/index.js +74 -11
- package/core/skill-loader.js +22 -8
- package/mcp/server.js +313 -0
- package/package.json +9 -3
package/core/index.js
CHANGED
|
@@ -8,6 +8,7 @@ const LearningEngine = require('./learning-engine');
|
|
|
8
8
|
const SceneMatcher = require('./scene-matcher');
|
|
9
9
|
const ConfigManager = require('./config-manager');
|
|
10
10
|
const ComponentRegistry = require('./component-registry');
|
|
11
|
+
const ModelManager = require('./ai/model-manager');
|
|
11
12
|
|
|
12
13
|
class FlowMind {
|
|
13
14
|
constructor(options = {}) {
|
|
@@ -16,6 +17,7 @@ class FlowMind {
|
|
|
16
17
|
this.matcher = new SceneMatcher(this.config, this.learning);
|
|
17
18
|
this.components = new ComponentRegistry(this.config);
|
|
18
19
|
this.skills = new SkillLoader(this.config, this.learning, this.components);
|
|
20
|
+
this.ai = new ModelManager(options.ai || {});
|
|
19
21
|
this.initialized = false;
|
|
20
22
|
}
|
|
21
23
|
|
|
@@ -32,6 +34,13 @@ class FlowMind {
|
|
|
32
34
|
await this.skills.loadAll();
|
|
33
35
|
await this.matcher.loadScenes();
|
|
34
36
|
|
|
37
|
+
// Initialize AI model manager
|
|
38
|
+
try {
|
|
39
|
+
await this.ai.init();
|
|
40
|
+
} catch (error) {
|
|
41
|
+
console.warn(`AI model initialization failed: ${error.message}. Falling back to rule-based engine.`);
|
|
42
|
+
}
|
|
43
|
+
|
|
35
44
|
this.initialized = true;
|
|
36
45
|
return this;
|
|
37
46
|
}
|
|
@@ -47,32 +56,70 @@ class FlowMind {
|
|
|
47
56
|
const startTime = Date.now();
|
|
48
57
|
|
|
49
58
|
try {
|
|
50
|
-
// 1.
|
|
51
|
-
const
|
|
59
|
+
// 1. AI Intent Understanding (if available)
|
|
60
|
+
const intent = await this.ai.understandIntent(input, context);
|
|
61
|
+
|
|
62
|
+
// 2. Check for learning patterns (corrections, feedback)
|
|
63
|
+
// Use AI to analyze learning feedback if available
|
|
64
|
+
const aiLearningResult = await this.ai.analyzeLearningFeedback(input, context);
|
|
65
|
+
const learningResult = aiLearningResult?.isLearning
|
|
66
|
+
? aiLearningResult
|
|
67
|
+
: await this.learning.detectLearning(input, context);
|
|
52
68
|
if (learningResult) {
|
|
53
69
|
return this.formatLearningResponse(learningResult);
|
|
54
70
|
}
|
|
55
71
|
|
|
56
|
-
//
|
|
57
|
-
const sceneMatch = await this.matcher.match(input);
|
|
72
|
+
// 3. Check scene mappings (with AI intent if available)
|
|
73
|
+
const sceneMatch = await this.matcher.match(input, intent);
|
|
58
74
|
if (sceneMatch && sceneMatch.confidence >= 0.7) {
|
|
59
75
|
return this.executeSceneWorkflow(sceneMatch, input, context);
|
|
60
76
|
}
|
|
61
77
|
|
|
62
|
-
//
|
|
63
|
-
|
|
78
|
+
// 4. Select skill (AI-assisted if available)
|
|
79
|
+
let skill = null;
|
|
80
|
+
const candidates = await this.skills.getCandidates(input, context);
|
|
81
|
+
|
|
82
|
+
if (candidates.length > 0) {
|
|
83
|
+
// Use AI to select skill if available
|
|
84
|
+
const aiSelection = await this.ai.selectSkill(input, candidates);
|
|
85
|
+
if (aiSelection && aiSelection.selectedSkill) {
|
|
86
|
+
skill = this.skills.get(aiSelection.selectedSkill);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Fallback to rule-based selection
|
|
91
|
+
if (!skill) {
|
|
92
|
+
skill = await this.skills.select(input, context);
|
|
93
|
+
}
|
|
94
|
+
|
|
64
95
|
if (!skill) {
|
|
65
96
|
return this.formatError('No matching skill found', input);
|
|
66
97
|
}
|
|
67
98
|
|
|
68
|
-
//
|
|
69
|
-
const
|
|
99
|
+
// 5. Extract parameters using AI (if available)
|
|
100
|
+
const extractedParams = await this.ai.extractParameters(input, skill.name);
|
|
101
|
+
|
|
102
|
+
// 6. Execute with learning applied
|
|
103
|
+
const enhancedContext = {
|
|
104
|
+
...context,
|
|
105
|
+
...extractedParams,
|
|
106
|
+
intent: intent
|
|
107
|
+
};
|
|
108
|
+
const result = await this.executeWithLearning(skill, input, enhancedContext);
|
|
70
109
|
|
|
71
|
-
//
|
|
72
|
-
|
|
110
|
+
// 7. Generate AI summary (if available)
|
|
111
|
+
const summary = await this.ai.summarizeResult(result, {
|
|
112
|
+
skill: skill.name,
|
|
113
|
+
intent: intent
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
// 8. Format and return
|
|
117
|
+
return this.formatResult(summary || result, {
|
|
73
118
|
skill: skill.name,
|
|
74
119
|
duration: Date.now() - startTime,
|
|
75
|
-
sceneMatch: sceneMatch
|
|
120
|
+
sceneMatch: sceneMatch,
|
|
121
|
+
intent: intent,
|
|
122
|
+
aiEnhanced: !!summary
|
|
76
123
|
});
|
|
77
124
|
|
|
78
125
|
} catch (error) {
|
|
@@ -205,6 +252,22 @@ class FlowMind {
|
|
|
205
252
|
return this.components.getStatus();
|
|
206
253
|
}
|
|
207
254
|
|
|
255
|
+
/**
|
|
256
|
+
* Get AI model status
|
|
257
|
+
* @returns {object}
|
|
258
|
+
*/
|
|
259
|
+
getAIStatus() {
|
|
260
|
+
return this.ai.getStatus();
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Check if AI is available
|
|
265
|
+
* @returns {boolean}
|
|
266
|
+
*/
|
|
267
|
+
hasAI() {
|
|
268
|
+
return this.ai.hasAvailableProvider();
|
|
269
|
+
}
|
|
270
|
+
|
|
208
271
|
/**
|
|
209
272
|
* Export learnings
|
|
210
273
|
*/
|
package/core/skill-loader.js
CHANGED
|
@@ -225,6 +225,23 @@ class SkillLoader {
|
|
|
225
225
|
* Select best skill for input
|
|
226
226
|
*/
|
|
227
227
|
async select(input, context = {}) {
|
|
228
|
+
const candidates = await this.getCandidates(input, context);
|
|
229
|
+
|
|
230
|
+
if (candidates.length === 0) {
|
|
231
|
+
return null;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Sort by score (highest first)
|
|
235
|
+
candidates.sort((a, b) => b.score - a.score);
|
|
236
|
+
|
|
237
|
+
return candidates[0].skill;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Get candidate skills for input
|
|
242
|
+
* Returns skills that can handle the input with their scores
|
|
243
|
+
*/
|
|
244
|
+
async getCandidates(input, context = {}) {
|
|
228
245
|
const candidates = [];
|
|
229
246
|
|
|
230
247
|
for (const [name, skill] of this.skills) {
|
|
@@ -232,7 +249,11 @@ class SkillLoader {
|
|
|
232
249
|
const canHandle = await skill.canHandle(input, context);
|
|
233
250
|
if (canHandle) {
|
|
234
251
|
candidates.push({
|
|
252
|
+
name: skill.name,
|
|
235
253
|
skill: skill,
|
|
254
|
+
description: skill.definition?.description || '',
|
|
255
|
+
triggers: skill.definition?.triggers || [],
|
|
256
|
+
category: skill.definition?.category || skill.definition?.metadata?.category || '',
|
|
236
257
|
score: this.calculateSkillScore(skill, input, context)
|
|
237
258
|
});
|
|
238
259
|
}
|
|
@@ -241,14 +262,7 @@ class SkillLoader {
|
|
|
241
262
|
}
|
|
242
263
|
}
|
|
243
264
|
|
|
244
|
-
|
|
245
|
-
return null;
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
// Sort by score (highest first)
|
|
249
|
-
candidates.sort((a, b) => b.score - a.score);
|
|
250
|
-
|
|
251
|
-
return candidates[0].skill;
|
|
265
|
+
return candidates;
|
|
252
266
|
}
|
|
253
267
|
|
|
254
268
|
/**
|
package/mcp/server.js
ADDED
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* FlowMind MCP Server
|
|
5
|
+
* 让 Claude/Codex 可以直接调用 FlowMind 内部流程
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const FlowMind = require('../core');
|
|
9
|
+
|
|
10
|
+
// MCP Server 实现
|
|
11
|
+
class FlowMindMCPServer {
|
|
12
|
+
constructor() {
|
|
13
|
+
this.flowmind = null;
|
|
14
|
+
this.initialized = false;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async init() {
|
|
18
|
+
if (this.initialized) return;
|
|
19
|
+
|
|
20
|
+
this.flowmind = new FlowMind();
|
|
21
|
+
await this.flowmind.init();
|
|
22
|
+
this.initialized = true;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* 获取所有可用工具
|
|
27
|
+
*/
|
|
28
|
+
getTools() {
|
|
29
|
+
const skills = this.flowmind.skills.list();
|
|
30
|
+
const tools = [];
|
|
31
|
+
|
|
32
|
+
// 添加核心工具
|
|
33
|
+
tools.push({
|
|
34
|
+
name: 'flowmind_process',
|
|
35
|
+
description: 'Process a request using FlowMind AI agent. This is the main entry point for using FlowMind.',
|
|
36
|
+
inputSchema: {
|
|
37
|
+
type: 'object',
|
|
38
|
+
properties: {
|
|
39
|
+
input: {
|
|
40
|
+
type: 'string',
|
|
41
|
+
description: 'The request to process'
|
|
42
|
+
},
|
|
43
|
+
context: {
|
|
44
|
+
type: 'object',
|
|
45
|
+
description: 'Optional context for the request'
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
required: ['input']
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
tools.push({
|
|
53
|
+
name: 'flowmind_list_skills',
|
|
54
|
+
description: 'List all available FlowMind skills',
|
|
55
|
+
inputSchema: {
|
|
56
|
+
type: 'object',
|
|
57
|
+
properties: {}
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
tools.push({
|
|
62
|
+
name: 'flowmind_get_skill',
|
|
63
|
+
description: 'Get detailed information about a specific skill',
|
|
64
|
+
inputSchema: {
|
|
65
|
+
type: 'object',
|
|
66
|
+
properties: {
|
|
67
|
+
name: {
|
|
68
|
+
type: 'string',
|
|
69
|
+
description: 'Skill name'
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
required: ['name']
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
tools.push({
|
|
77
|
+
name: 'flowmind_ai_status',
|
|
78
|
+
description: 'Get AI model status and configuration',
|
|
79
|
+
inputSchema: {
|
|
80
|
+
type: 'object',
|
|
81
|
+
properties: {}
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
tools.push({
|
|
86
|
+
name: 'flowmind_learning_stats',
|
|
87
|
+
description: 'Get learning statistics',
|
|
88
|
+
inputSchema: {
|
|
89
|
+
type: 'object',
|
|
90
|
+
properties: {}
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// 添加每个技能作为独立工具
|
|
95
|
+
for (const skill of skills) {
|
|
96
|
+
tools.push({
|
|
97
|
+
name: `flowmind_skill_${skill.name}`,
|
|
98
|
+
description: skill.description || `Execute ${skill.name} skill`,
|
|
99
|
+
inputSchema: {
|
|
100
|
+
type: 'object',
|
|
101
|
+
properties: {
|
|
102
|
+
input: {
|
|
103
|
+
type: 'string',
|
|
104
|
+
description: 'Input for the skill'
|
|
105
|
+
},
|
|
106
|
+
context: {
|
|
107
|
+
type: 'object',
|
|
108
|
+
description: 'Optional context'
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
required: ['input']
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return tools;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* 调用工具
|
|
121
|
+
*/
|
|
122
|
+
async callTool(name, args) {
|
|
123
|
+
await this.init();
|
|
124
|
+
|
|
125
|
+
try {
|
|
126
|
+
// 核心工具
|
|
127
|
+
if (name === 'flowmind_process') {
|
|
128
|
+
const result = await this.flowmind.process(args.input, args.context || {});
|
|
129
|
+
return {
|
|
130
|
+
content: [{
|
|
131
|
+
type: 'text',
|
|
132
|
+
text: JSON.stringify(result, null, 2)
|
|
133
|
+
}]
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (name === 'flowmind_list_skills') {
|
|
138
|
+
const skills = this.flowmind.skills.list();
|
|
139
|
+
return {
|
|
140
|
+
content: [{
|
|
141
|
+
type: 'text',
|
|
142
|
+
text: JSON.stringify({ skills }, null, 2)
|
|
143
|
+
}]
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if (name === 'flowmind_get_skill') {
|
|
148
|
+
const skill = this.flowmind.skills.get(args.name);
|
|
149
|
+
if (!skill) {
|
|
150
|
+
return {
|
|
151
|
+
content: [{
|
|
152
|
+
type: 'text',
|
|
153
|
+
text: JSON.stringify({ error: `Skill not found: ${args.name}` })
|
|
154
|
+
}],
|
|
155
|
+
isError: true
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
return {
|
|
159
|
+
content: [{
|
|
160
|
+
type: 'text',
|
|
161
|
+
text: JSON.stringify({
|
|
162
|
+
name: skill.name,
|
|
163
|
+
description: skill.definition?.description,
|
|
164
|
+
category: skill.definition?.category,
|
|
165
|
+
triggers: skill.definition?.triggers,
|
|
166
|
+
componentDependencies: skill.definition?.componentDependencies
|
|
167
|
+
}, null, 2)
|
|
168
|
+
}]
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if (name === 'flowmind_ai_status') {
|
|
173
|
+
const status = this.flowmind.getAIStatus();
|
|
174
|
+
return {
|
|
175
|
+
content: [{
|
|
176
|
+
type: 'text',
|
|
177
|
+
text: JSON.stringify(status, null, 2)
|
|
178
|
+
}]
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (name === 'flowmind_learning_stats') {
|
|
183
|
+
const stats = await this.flowmind.getStats();
|
|
184
|
+
return {
|
|
185
|
+
content: [{
|
|
186
|
+
type: 'text',
|
|
187
|
+
text: JSON.stringify(stats, null, 2)
|
|
188
|
+
}]
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// 技能工具
|
|
193
|
+
if (name.startsWith('flowmind_skill_')) {
|
|
194
|
+
const skillName = name.replace('flowmind_skill_', '');
|
|
195
|
+
const skill = this.flowmind.skills.get(skillName);
|
|
196
|
+
|
|
197
|
+
if (!skill) {
|
|
198
|
+
return {
|
|
199
|
+
content: [{
|
|
200
|
+
type: 'text',
|
|
201
|
+
text: JSON.stringify({ error: `Skill not found: ${skillName}` })
|
|
202
|
+
}],
|
|
203
|
+
isError: true
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
const result = await this.flowmind.executeWithLearning(skill, args.input, args.context || {});
|
|
208
|
+
return {
|
|
209
|
+
content: [{
|
|
210
|
+
type: 'text',
|
|
211
|
+
text: JSON.stringify(result, null, 2)
|
|
212
|
+
}]
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return {
|
|
217
|
+
content: [{
|
|
218
|
+
type: 'text',
|
|
219
|
+
text: JSON.stringify({ error: `Unknown tool: ${name}` })
|
|
220
|
+
}],
|
|
221
|
+
isError: true
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
} catch (error) {
|
|
225
|
+
return {
|
|
226
|
+
content: [{
|
|
227
|
+
type: 'text',
|
|
228
|
+
text: JSON.stringify({ error: error.message })
|
|
229
|
+
}],
|
|
230
|
+
isError: true
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// 启动 MCP Server
|
|
237
|
+
async function main() {
|
|
238
|
+
const server = new FlowMindMCPServer();
|
|
239
|
+
|
|
240
|
+
// 读取 stdin,写入 stdout
|
|
241
|
+
const readline = require('readline');
|
|
242
|
+
const rl = readline.createInterface({
|
|
243
|
+
input: process.stdin,
|
|
244
|
+
output: process.stdout,
|
|
245
|
+
terminal: false
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
rl.on('line', async (line) => {
|
|
249
|
+
try {
|
|
250
|
+
const request = JSON.parse(line);
|
|
251
|
+
let response;
|
|
252
|
+
|
|
253
|
+
if (request.method === 'initialize') {
|
|
254
|
+
response = {
|
|
255
|
+
jsonrpc: '2.0',
|
|
256
|
+
id: request.id,
|
|
257
|
+
result: {
|
|
258
|
+
protocolVersion: '2024-11-05',
|
|
259
|
+
capabilities: {
|
|
260
|
+
tools: {}
|
|
261
|
+
},
|
|
262
|
+
serverInfo: {
|
|
263
|
+
name: 'flowmind',
|
|
264
|
+
version: '1.0.1'
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
};
|
|
268
|
+
} else if (request.method === 'tools/list') {
|
|
269
|
+
await server.init();
|
|
270
|
+
const tools = server.getTools();
|
|
271
|
+
response = {
|
|
272
|
+
jsonrpc: '2.0',
|
|
273
|
+
id: request.id,
|
|
274
|
+
result: { tools }
|
|
275
|
+
};
|
|
276
|
+
} else if (request.method === 'tools/call') {
|
|
277
|
+
const result = await server.callTool(request.params.name, request.params.arguments || {});
|
|
278
|
+
response = {
|
|
279
|
+
jsonrpc: '2.0',
|
|
280
|
+
id: request.id,
|
|
281
|
+
result
|
|
282
|
+
};
|
|
283
|
+
} else {
|
|
284
|
+
response = {
|
|
285
|
+
jsonrpc: '2.0',
|
|
286
|
+
id: request.id,
|
|
287
|
+
error: {
|
|
288
|
+
code: -32601,
|
|
289
|
+
message: `Method not found: ${request.method}`
|
|
290
|
+
}
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
process.stdout.write(JSON.stringify(response) + '\n');
|
|
295
|
+
} catch (error) {
|
|
296
|
+
const response = {
|
|
297
|
+
jsonrpc: '2.0',
|
|
298
|
+
id: null,
|
|
299
|
+
error: {
|
|
300
|
+
code: -32700,
|
|
301
|
+
message: 'Parse error'
|
|
302
|
+
}
|
|
303
|
+
};
|
|
304
|
+
process.stdout.write(JSON.stringify(response) + '\n');
|
|
305
|
+
}
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
// 初始化
|
|
309
|
+
await server.init();
|
|
310
|
+
console.error('FlowMind MCP Server started');
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
main().catch(console.error);
|
package/package.json
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "flowmind",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "The AI Agent That Learns How You Work - Stop repeating yourself, FlowMind learns your workflows and applies them automatically.",
|
|
5
5
|
"main": "core/index.js",
|
|
6
6
|
"bin": {
|
|
7
|
-
"flowmind": "./bin/flowmind.js"
|
|
7
|
+
"flowmind": "./bin/flowmind.js",
|
|
8
|
+
"flowmind-mcp": "./mcp/server.js"
|
|
8
9
|
},
|
|
9
10
|
"scripts": {
|
|
10
11
|
"start": "node core/index.js",
|
|
12
|
+
"mcp": "node mcp/server.js",
|
|
11
13
|
"test": "jest",
|
|
12
14
|
"test:coverage": "jest --coverage",
|
|
13
15
|
"lint": "eslint .",
|
|
@@ -21,7 +23,10 @@
|
|
|
21
23
|
"learning-system",
|
|
22
24
|
"code-review",
|
|
23
25
|
"log-analysis",
|
|
24
|
-
"devops"
|
|
26
|
+
"devops",
|
|
27
|
+
"mcp-server",
|
|
28
|
+
"claude-integration",
|
|
29
|
+
"codex-integration"
|
|
25
30
|
],
|
|
26
31
|
"author": "FlowMind Technologies",
|
|
27
32
|
"license": "MIT",
|
|
@@ -36,6 +41,7 @@
|
|
|
36
41
|
"files": [
|
|
37
42
|
"bin/",
|
|
38
43
|
"core/",
|
|
44
|
+
"mcp/",
|
|
39
45
|
"skills/",
|
|
40
46
|
"scripts/",
|
|
41
47
|
"templates/",
|