apteva 0.4.10 → 0.4.12
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/dist/index.html
CHANGED
package/package.json
CHANGED
package/src/mcp-platform.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Built-in MCP server that exposes the Apteva platform API as MCP tools
|
|
2
2
|
// This allows the meta agent (Apteva Assistant) to control the platform
|
|
3
3
|
|
|
4
|
-
import { AgentDB, ProjectDB, McpServerDB, TelemetryDB, generateId } from "./db";
|
|
4
|
+
import { AgentDB, ProjectDB, McpServerDB, SkillDB, TelemetryDB, generateId } from "./db";
|
|
5
5
|
import { getProvidersWithStatus, PROVIDERS } from "./providers";
|
|
6
6
|
import { startAgentProcess, setAgentStatus, toApiAgent, META_AGENT_ID, agentFetch } from "./routes/api/agent-utils";
|
|
7
7
|
import { agentProcesses } from "./server";
|
|
@@ -48,24 +48,47 @@ const PLATFORM_TOOLS = [
|
|
|
48
48
|
},
|
|
49
49
|
{
|
|
50
50
|
name: "create_agent",
|
|
51
|
-
description:
|
|
51
|
+
description: `Create a new AI agent. The provider must have an API key configured — use list_providers first to check.
|
|
52
|
+
|
|
53
|
+
PROVIDERS & MODELS (use list_providers to see which have keys):
|
|
54
|
+
- anthropic: claude-sonnet-4-5 (recommended), claude-haiku-4-5 (fast/cheap)
|
|
55
|
+
- openai: gpt-4o (recommended), gpt-4o-mini (fast/cheap)
|
|
56
|
+
- groq: llama-3.3-70b-versatile (recommended), llama-3.1-8b-instant (fast)
|
|
57
|
+
- gemini: gemini-3-pro-preview (recommended), gemini-3-flash-preview (fast)
|
|
58
|
+
- xai: grok-2 (recommended), grok-2-mini (fast)
|
|
59
|
+
- together: moonshotai/Kimi-K2.5 (recommended), moonshotai/Kimi-K2-Thinking (reasoning)
|
|
60
|
+
- fireworks: accounts/fireworks/models/kimi-k2p5, accounts/fireworks/models/kimi-k2-thinking
|
|
61
|
+
- moonshot: moonshot-v1-128k (recommended), moonshot-v1-32k (fast)
|
|
62
|
+
- ollama: llama3.3, llama3.2, qwen2.5, mistral, deepseek-r1 (local, no API key needed)
|
|
63
|
+
|
|
64
|
+
FEATURES (all optional, default false):
|
|
65
|
+
- memory: Persistent memory across conversations — agent remembers past interactions. Requires OpenAI key for embeddings.
|
|
66
|
+
- tasks: Task scheduling — agent can create, schedule, and track tasks. Supports recurring tasks.
|
|
67
|
+
- vision: Image & PDF understanding — agent can analyze uploaded images and PDFs.
|
|
68
|
+
- mcp: MCP tool use — agent can use tools from assigned MCP servers. Enable this if you plan to assign MCP servers.
|
|
69
|
+
- files: File management — agent can read, write, and manage files in its workspace.
|
|
70
|
+
|
|
71
|
+
TIPS:
|
|
72
|
+
- Always provide a descriptive system_prompt that tells the agent what it does and how to behave.
|
|
73
|
+
- Assign to a project_id to organize agents. Use list_projects to see available projects.
|
|
74
|
+
- After creating, use start_agent to run it. Then assign MCP servers or skills as needed.`,
|
|
52
75
|
inputSchema: {
|
|
53
76
|
type: "object",
|
|
54
77
|
properties: {
|
|
55
|
-
name: { type: "string", description: "Agent name" },
|
|
56
|
-
provider: { type: "string", description: "LLM provider ID
|
|
57
|
-
model: { type: "string", description: "Model ID
|
|
58
|
-
system_prompt: { type: "string", description: "
|
|
59
|
-
project_id: { type: "string", description: "Project ID to assign the agent to (optional)" },
|
|
78
|
+
name: { type: "string", description: "Agent name (e.g. 'Customer Support', 'Code Reviewer')" },
|
|
79
|
+
provider: { type: "string", description: "LLM provider ID: anthropic, openai, groq, gemini, xai, together, fireworks, moonshot, ollama" },
|
|
80
|
+
model: { type: "string", description: "Model ID — see tool description for full list per provider" },
|
|
81
|
+
system_prompt: { type: "string", description: "Instructions for the agent. Describe its role, personality, and capabilities. This is the most important field for agent behavior." },
|
|
82
|
+
project_id: { type: "string", description: "Project ID to assign the agent to (optional). Use list_projects to find IDs." },
|
|
60
83
|
features: {
|
|
61
84
|
type: "object",
|
|
62
|
-
description: "Feature flags
|
|
85
|
+
description: "Feature flags to enable. All default to false. See tool description for details on each feature.",
|
|
63
86
|
properties: {
|
|
64
|
-
memory: { type: "boolean" },
|
|
65
|
-
tasks: { type: "boolean" },
|
|
66
|
-
vision: { type: "boolean" },
|
|
67
|
-
mcp: { type: "boolean" },
|
|
68
|
-
files: { type: "boolean" },
|
|
87
|
+
memory: { type: "boolean", description: "Persistent memory across conversations (requires OpenAI key for embeddings)" },
|
|
88
|
+
tasks: { type: "boolean", description: "Task scheduling and tracking" },
|
|
89
|
+
vision: { type: "boolean", description: "Image and PDF understanding" },
|
|
90
|
+
mcp: { type: "boolean", description: "MCP tool use — required if assigning MCP servers" },
|
|
91
|
+
files: { type: "boolean", description: "File read/write in agent workspace" },
|
|
69
92
|
},
|
|
70
93
|
},
|
|
71
94
|
},
|
|
@@ -74,17 +97,27 @@ const PLATFORM_TOOLS = [
|
|
|
74
97
|
},
|
|
75
98
|
{
|
|
76
99
|
name: "update_agent",
|
|
77
|
-
description: "Update an existing agent's configuration. Only provide fields you want to change.",
|
|
100
|
+
description: "Update an existing agent's configuration. Only provide fields you want to change. If the agent is running, restart it after updating for changes to take effect.",
|
|
78
101
|
inputSchema: {
|
|
79
102
|
type: "object",
|
|
80
103
|
properties: {
|
|
81
104
|
agent_id: { type: "string", description: "The agent ID to update" },
|
|
82
|
-
name: { type: "string", description: "New name" },
|
|
83
|
-
model: { type: "string", description: "New model ID" },
|
|
84
|
-
provider: { type: "string", description: "New provider ID" },
|
|
85
|
-
system_prompt: { type: "string", description: "New system prompt" },
|
|
86
|
-
project_id: { type: "string", description: "New project ID
|
|
87
|
-
features: {
|
|
105
|
+
name: { type: "string", description: "New display name" },
|
|
106
|
+
model: { type: "string", description: "New model ID (see create_agent for available models per provider)" },
|
|
107
|
+
provider: { type: "string", description: "New provider ID (the new provider must have an API key configured)" },
|
|
108
|
+
system_prompt: { type: "string", description: "New system prompt / instructions" },
|
|
109
|
+
project_id: { type: "string", description: "New project ID, or null to unassign from project" },
|
|
110
|
+
features: {
|
|
111
|
+
type: "object",
|
|
112
|
+
description: "Feature flags to update (only provided flags are changed, others remain as-is)",
|
|
113
|
+
properties: {
|
|
114
|
+
memory: { type: "boolean" },
|
|
115
|
+
tasks: { type: "boolean" },
|
|
116
|
+
vision: { type: "boolean" },
|
|
117
|
+
mcp: { type: "boolean" },
|
|
118
|
+
files: { type: "boolean" },
|
|
119
|
+
},
|
|
120
|
+
},
|
|
88
121
|
},
|
|
89
122
|
required: ["agent_id"],
|
|
90
123
|
},
|
|
@@ -102,7 +135,7 @@ const PLATFORM_TOOLS = [
|
|
|
102
135
|
},
|
|
103
136
|
{
|
|
104
137
|
name: "start_agent",
|
|
105
|
-
description: "Start a stopped agent. The agent's provider must have an API key configured.",
|
|
138
|
+
description: "Start a stopped agent. The agent's provider must have an API key configured. Starting spawns a process, waits for health check, and pushes configuration (model, features, MCP servers, skills). Takes a few seconds.",
|
|
106
139
|
inputSchema: {
|
|
107
140
|
type: "object",
|
|
108
141
|
properties: {
|
|
@@ -153,10 +186,84 @@ const PLATFORM_TOOLS = [
|
|
|
153
186
|
},
|
|
154
187
|
{
|
|
155
188
|
name: "list_mcp_servers",
|
|
156
|
-
description: "List all configured MCP servers (tool integrations).",
|
|
189
|
+
description: "List all configured MCP servers (tool integrations). Optionally filter by project.",
|
|
157
190
|
inputSchema: {
|
|
158
191
|
type: "object",
|
|
159
|
-
properties: {
|
|
192
|
+
properties: {
|
|
193
|
+
project_id: { type: "string", description: "Filter by project ID (optional)" },
|
|
194
|
+
},
|
|
195
|
+
},
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
name: "get_mcp_server",
|
|
199
|
+
description: "Get detailed information about an MCP server by ID.",
|
|
200
|
+
inputSchema: {
|
|
201
|
+
type: "object",
|
|
202
|
+
properties: {
|
|
203
|
+
server_id: { type: "string", description: "The MCP server ID" },
|
|
204
|
+
},
|
|
205
|
+
required: ["server_id"],
|
|
206
|
+
},
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
name: "create_mcp_server",
|
|
210
|
+
description: `Create a new MCP server configuration. MCP servers provide tools that agents can use (web search, file access, APIs, etc).
|
|
211
|
+
|
|
212
|
+
SERVER TYPES:
|
|
213
|
+
- http: Remote MCP server accessible via URL. Provide url and optional auth headers. Ready to use immediately.
|
|
214
|
+
- npm: Node.js MCP server from npm. Provide package name (e.g. '@modelcontextprotocol/server-filesystem'). Needs to be started.
|
|
215
|
+
- pip: Python MCP server from PyPI. Provide package name. Needs to be started.
|
|
216
|
+
- custom: Custom command. Provide command and args. Needs to be started.
|
|
217
|
+
|
|
218
|
+
After creating, assign to agents with assign_mcp_server_to_agent. HTTP servers work immediately; npm/pip/custom servers need to be started from the MCP page in the UI.`,
|
|
219
|
+
inputSchema: {
|
|
220
|
+
type: "object",
|
|
221
|
+
properties: {
|
|
222
|
+
name: { type: "string", description: "Display name (e.g. 'Filesystem', 'Web Search', 'GitHub')" },
|
|
223
|
+
type: { type: "string", description: "Server type: http, npm, pip, or custom" },
|
|
224
|
+
url: { type: "string", description: "For http type: the remote MCP server URL (e.g. 'https://mcp.example.com/sse')" },
|
|
225
|
+
headers: { type: "object", description: "For http type: auth headers as key-value pairs" },
|
|
226
|
+
package: { type: "string", description: "For npm/pip type: package name" },
|
|
227
|
+
command: { type: "string", description: "For custom type: executable command" },
|
|
228
|
+
args: { type: "string", description: "Command arguments string (optional)" },
|
|
229
|
+
project_id: { type: "string", description: "Scope to a project (optional). null = available globally to all agents." },
|
|
230
|
+
},
|
|
231
|
+
required: ["name", "type"],
|
|
232
|
+
},
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
name: "delete_mcp_server",
|
|
236
|
+
description: "Delete an MCP server. It must be stopped first.",
|
|
237
|
+
inputSchema: {
|
|
238
|
+
type: "object",
|
|
239
|
+
properties: {
|
|
240
|
+
server_id: { type: "string", description: "The MCP server ID to delete" },
|
|
241
|
+
},
|
|
242
|
+
required: ["server_id"],
|
|
243
|
+
},
|
|
244
|
+
},
|
|
245
|
+
{
|
|
246
|
+
name: "assign_mcp_server_to_agent",
|
|
247
|
+
description: "Assign an MCP server to an agent so the agent can use its tools. This automatically enables the MCP feature on the agent. If the agent is running, restart it for changes to take effect.",
|
|
248
|
+
inputSchema: {
|
|
249
|
+
type: "object",
|
|
250
|
+
properties: {
|
|
251
|
+
agent_id: { type: "string", description: "The agent ID" },
|
|
252
|
+
server_id: { type: "string", description: "The MCP server ID to assign" },
|
|
253
|
+
},
|
|
254
|
+
required: ["agent_id", "server_id"],
|
|
255
|
+
},
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
name: "unassign_mcp_server_from_agent",
|
|
259
|
+
description: "Remove an MCP server from an agent.",
|
|
260
|
+
inputSchema: {
|
|
261
|
+
type: "object",
|
|
262
|
+
properties: {
|
|
263
|
+
agent_id: { type: "string", description: "The agent ID" },
|
|
264
|
+
server_id: { type: "string", description: "The MCP server ID to remove" },
|
|
265
|
+
},
|
|
266
|
+
required: ["agent_id", "server_id"],
|
|
160
267
|
},
|
|
161
268
|
},
|
|
162
269
|
{
|
|
@@ -179,6 +286,75 @@ const PLATFORM_TOOLS = [
|
|
|
179
286
|
required: ["agent_id", "message"],
|
|
180
287
|
},
|
|
181
288
|
},
|
|
289
|
+
// Skills management
|
|
290
|
+
{
|
|
291
|
+
name: "list_skills",
|
|
292
|
+
description: "List all installed skills. Skills are reusable instruction sets (like prompt templates with tool permissions) that give agents specialized capabilities. Skills can be installed from the SkillsMP marketplace or created locally.",
|
|
293
|
+
inputSchema: {
|
|
294
|
+
type: "object",
|
|
295
|
+
properties: {
|
|
296
|
+
enabled_only: { type: "boolean", description: "Only return enabled skills (optional, default false)" },
|
|
297
|
+
},
|
|
298
|
+
},
|
|
299
|
+
},
|
|
300
|
+
{
|
|
301
|
+
name: "get_skill",
|
|
302
|
+
description: "Get detailed information about a skill by ID, including its full instructions content.",
|
|
303
|
+
inputSchema: {
|
|
304
|
+
type: "object",
|
|
305
|
+
properties: {
|
|
306
|
+
skill_id: { type: "string", description: "The skill ID" },
|
|
307
|
+
},
|
|
308
|
+
required: ["skill_id"],
|
|
309
|
+
},
|
|
310
|
+
},
|
|
311
|
+
{
|
|
312
|
+
name: "toggle_skill",
|
|
313
|
+
description: "Enable or disable a skill.",
|
|
314
|
+
inputSchema: {
|
|
315
|
+
type: "object",
|
|
316
|
+
properties: {
|
|
317
|
+
skill_id: { type: "string", description: "The skill ID" },
|
|
318
|
+
enabled: { type: "boolean", description: "Whether to enable (true) or disable (false) the skill" },
|
|
319
|
+
},
|
|
320
|
+
required: ["skill_id", "enabled"],
|
|
321
|
+
},
|
|
322
|
+
},
|
|
323
|
+
{
|
|
324
|
+
name: "assign_skill_to_agent",
|
|
325
|
+
description: "Assign a skill to an agent. The skill's instructions and tool permissions will be pushed to the agent on next start/restart.",
|
|
326
|
+
inputSchema: {
|
|
327
|
+
type: "object",
|
|
328
|
+
properties: {
|
|
329
|
+
agent_id: { type: "string", description: "The agent ID" },
|
|
330
|
+
skill_id: { type: "string", description: "The skill ID to assign" },
|
|
331
|
+
},
|
|
332
|
+
required: ["agent_id", "skill_id"],
|
|
333
|
+
},
|
|
334
|
+
},
|
|
335
|
+
{
|
|
336
|
+
name: "unassign_skill_from_agent",
|
|
337
|
+
description: "Remove a skill from an agent.",
|
|
338
|
+
inputSchema: {
|
|
339
|
+
type: "object",
|
|
340
|
+
properties: {
|
|
341
|
+
agent_id: { type: "string", description: "The agent ID" },
|
|
342
|
+
skill_id: { type: "string", description: "The skill ID to remove" },
|
|
343
|
+
},
|
|
344
|
+
required: ["agent_id", "skill_id"],
|
|
345
|
+
},
|
|
346
|
+
},
|
|
347
|
+
{
|
|
348
|
+
name: "delete_skill",
|
|
349
|
+
description: "Delete a skill. It will be unassigned from all agents.",
|
|
350
|
+
inputSchema: {
|
|
351
|
+
type: "object",
|
|
352
|
+
properties: {
|
|
353
|
+
skill_id: { type: "string", description: "The skill ID to delete" },
|
|
354
|
+
},
|
|
355
|
+
required: ["skill_id"],
|
|
356
|
+
},
|
|
357
|
+
},
|
|
182
358
|
];
|
|
183
359
|
|
|
184
360
|
// Tool execution handlers
|
|
@@ -351,24 +527,114 @@ async function executeTool(name: string, args: Record<string, any>): Promise<{ c
|
|
|
351
527
|
}
|
|
352
528
|
|
|
353
529
|
case "list_mcp_servers": {
|
|
354
|
-
const servers =
|
|
530
|
+
const servers = args.project_id
|
|
531
|
+
? McpServerDB.findByProject(args.project_id)
|
|
532
|
+
: McpServerDB.findAll();
|
|
355
533
|
const result = servers.map(s => ({
|
|
356
534
|
id: s.id,
|
|
357
535
|
name: s.name,
|
|
358
536
|
type: s.type,
|
|
359
537
|
status: s.status,
|
|
360
538
|
url: s.url,
|
|
539
|
+
package: s.package,
|
|
540
|
+
projectId: s.project_id,
|
|
361
541
|
}));
|
|
362
542
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
363
543
|
}
|
|
364
544
|
|
|
545
|
+
case "get_mcp_server": {
|
|
546
|
+
const server = McpServerDB.findById(args.server_id);
|
|
547
|
+
if (!server) {
|
|
548
|
+
return { content: [{ type: "text", text: `MCP server not found: ${args.server_id}` }], isError: true };
|
|
549
|
+
}
|
|
550
|
+
return { content: [{ type: "text", text: JSON.stringify({
|
|
551
|
+
id: server.id,
|
|
552
|
+
name: server.name,
|
|
553
|
+
type: server.type,
|
|
554
|
+
status: server.status,
|
|
555
|
+
url: server.url,
|
|
556
|
+
package: server.package,
|
|
557
|
+
command: server.command,
|
|
558
|
+
args: server.args,
|
|
559
|
+
port: server.port,
|
|
560
|
+
source: server.source,
|
|
561
|
+
projectId: server.project_id,
|
|
562
|
+
}, null, 2) }] };
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
case "create_mcp_server": {
|
|
566
|
+
const id = generateId();
|
|
567
|
+
const server = McpServerDB.create({
|
|
568
|
+
id,
|
|
569
|
+
name: args.name,
|
|
570
|
+
type: args.type || "http",
|
|
571
|
+
package: args.package || null,
|
|
572
|
+
pip_module: null,
|
|
573
|
+
command: args.command || null,
|
|
574
|
+
args: args.args || null,
|
|
575
|
+
env: {},
|
|
576
|
+
url: args.url || null,
|
|
577
|
+
headers: args.headers || {},
|
|
578
|
+
source: null,
|
|
579
|
+
project_id: args.project_id || null,
|
|
580
|
+
});
|
|
581
|
+
return { content: [{ type: "text", text: `MCP server created: ${JSON.stringify({ id: server.id, name: server.name, type: server.type }, null, 2)}` }] };
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
case "delete_mcp_server": {
|
|
585
|
+
const server = McpServerDB.findById(args.server_id);
|
|
586
|
+
if (!server) {
|
|
587
|
+
return { content: [{ type: "text", text: `MCP server not found: ${args.server_id}` }], isError: true };
|
|
588
|
+
}
|
|
589
|
+
if (server.status === "running") {
|
|
590
|
+
return { content: [{ type: "text", text: "Cannot delete a running MCP server. Stop it first." }], isError: true };
|
|
591
|
+
}
|
|
592
|
+
McpServerDB.delete(args.server_id);
|
|
593
|
+
return { content: [{ type: "text", text: `MCP server deleted: ${server.name} (${server.id})` }] };
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
case "assign_mcp_server_to_agent": {
|
|
597
|
+
const agent = AgentDB.findById(args.agent_id);
|
|
598
|
+
if (!agent) {
|
|
599
|
+
return { content: [{ type: "text", text: `Agent not found: ${args.agent_id}` }], isError: true };
|
|
600
|
+
}
|
|
601
|
+
const server = McpServerDB.findById(args.server_id);
|
|
602
|
+
if (!server) {
|
|
603
|
+
return { content: [{ type: "text", text: `MCP server not found: ${args.server_id}` }], isError: true };
|
|
604
|
+
}
|
|
605
|
+
const mcpServers = agent.mcp_servers || [];
|
|
606
|
+
if (mcpServers.includes(args.server_id)) {
|
|
607
|
+
return { content: [{ type: "text", text: `Server ${server.name} is already assigned to ${agent.name}` }] };
|
|
608
|
+
}
|
|
609
|
+
AgentDB.update(args.agent_id, { mcp_servers: [...mcpServers, args.server_id] });
|
|
610
|
+
// Enable MCP feature if not already
|
|
611
|
+
if (!agent.features.mcp) {
|
|
612
|
+
AgentDB.update(args.agent_id, { features: { ...agent.features, mcp: true } });
|
|
613
|
+
}
|
|
614
|
+
return { content: [{ type: "text", text: `Assigned MCP server "${server.name}" to agent "${agent.name}". Restart the agent for changes to take effect.` }] };
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
case "unassign_mcp_server_from_agent": {
|
|
618
|
+
const agent = AgentDB.findById(args.agent_id);
|
|
619
|
+
if (!agent) {
|
|
620
|
+
return { content: [{ type: "text", text: `Agent not found: ${args.agent_id}` }], isError: true };
|
|
621
|
+
}
|
|
622
|
+
const mcpServers = agent.mcp_servers || [];
|
|
623
|
+
if (!mcpServers.includes(args.server_id)) {
|
|
624
|
+
return { content: [{ type: "text", text: `Server is not assigned to this agent` }] };
|
|
625
|
+
}
|
|
626
|
+
AgentDB.update(args.agent_id, { mcp_servers: mcpServers.filter((id: string) => id !== args.server_id) });
|
|
627
|
+
return { content: [{ type: "text", text: `Removed MCP server from agent "${agent.name}". Restart the agent for changes to take effect.` }] };
|
|
628
|
+
}
|
|
629
|
+
|
|
365
630
|
case "get_dashboard_stats": {
|
|
366
631
|
const agentCount = AgentDB.count();
|
|
367
632
|
const runningCount = AgentDB.countRunning();
|
|
368
633
|
const projectCount = ProjectDB.count();
|
|
369
634
|
const providers = getProvidersWithStatus().filter(p => p.type === "llm");
|
|
370
635
|
const configuredProviders = providers.filter(p => p.hasKey).length;
|
|
371
|
-
const
|
|
636
|
+
const mcpServerCount = McpServerDB.findAll().length;
|
|
637
|
+
const skillCount = SkillDB.count();
|
|
372
638
|
|
|
373
639
|
return {
|
|
374
640
|
content: [{
|
|
@@ -377,7 +643,8 @@ async function executeTool(name: string, args: Record<string, any>): Promise<{ c
|
|
|
377
643
|
agents: { total: agentCount - 1, running: runningCount }, // -1 for meta agent
|
|
378
644
|
projects: projectCount,
|
|
379
645
|
providers: { total: providers.length, configured: configuredProviders },
|
|
380
|
-
mcpServers,
|
|
646
|
+
mcpServers: mcpServerCount,
|
|
647
|
+
skills: skillCount,
|
|
381
648
|
}, null, 2),
|
|
382
649
|
}],
|
|
383
650
|
};
|
|
@@ -413,6 +680,92 @@ async function executeTool(name: string, args: Record<string, any>): Promise<{ c
|
|
|
413
680
|
}
|
|
414
681
|
}
|
|
415
682
|
|
|
683
|
+
case "list_skills": {
|
|
684
|
+
const skills = args.enabled_only ? SkillDB.findEnabled() : SkillDB.findAll();
|
|
685
|
+
const result = skills.map(s => ({
|
|
686
|
+
id: s.id,
|
|
687
|
+
name: s.name,
|
|
688
|
+
description: s.description,
|
|
689
|
+
version: s.version,
|
|
690
|
+
enabled: s.enabled,
|
|
691
|
+
source: s.source,
|
|
692
|
+
projectId: s.project_id,
|
|
693
|
+
}));
|
|
694
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
case "get_skill": {
|
|
698
|
+
const skill = SkillDB.findById(args.skill_id);
|
|
699
|
+
if (!skill) {
|
|
700
|
+
return { content: [{ type: "text", text: `Skill not found: ${args.skill_id}` }], isError: true };
|
|
701
|
+
}
|
|
702
|
+
return { content: [{ type: "text", text: JSON.stringify({
|
|
703
|
+
id: skill.id,
|
|
704
|
+
name: skill.name,
|
|
705
|
+
description: skill.description,
|
|
706
|
+
content: skill.content.slice(0, 500) + (skill.content.length > 500 ? "..." : ""),
|
|
707
|
+
version: skill.version,
|
|
708
|
+
enabled: skill.enabled,
|
|
709
|
+
source: skill.source,
|
|
710
|
+
allowedTools: skill.allowed_tools,
|
|
711
|
+
projectId: skill.project_id,
|
|
712
|
+
}, null, 2) }] };
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
case "toggle_skill": {
|
|
716
|
+
const skill = SkillDB.findById(args.skill_id);
|
|
717
|
+
if (!skill) {
|
|
718
|
+
return { content: [{ type: "text", text: `Skill not found: ${args.skill_id}` }], isError: true };
|
|
719
|
+
}
|
|
720
|
+
SkillDB.setEnabled(args.skill_id, args.enabled);
|
|
721
|
+
return { content: [{ type: "text", text: `Skill "${skill.name}" ${args.enabled ? "enabled" : "disabled"}` }] };
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
case "assign_skill_to_agent": {
|
|
725
|
+
const agent = AgentDB.findById(args.agent_id);
|
|
726
|
+
if (!agent) {
|
|
727
|
+
return { content: [{ type: "text", text: `Agent not found: ${args.agent_id}` }], isError: true };
|
|
728
|
+
}
|
|
729
|
+
const skill = SkillDB.findById(args.skill_id);
|
|
730
|
+
if (!skill) {
|
|
731
|
+
return { content: [{ type: "text", text: `Skill not found: ${args.skill_id}` }], isError: true };
|
|
732
|
+
}
|
|
733
|
+
const skills = agent.skills || [];
|
|
734
|
+
if (skills.includes(args.skill_id)) {
|
|
735
|
+
return { content: [{ type: "text", text: `Skill "${skill.name}" is already assigned to "${agent.name}"` }] };
|
|
736
|
+
}
|
|
737
|
+
AgentDB.update(args.agent_id, { skills: [...skills, args.skill_id] });
|
|
738
|
+
return { content: [{ type: "text", text: `Assigned skill "${skill.name}" to agent "${agent.name}". Restart the agent for changes to take effect.` }] };
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
case "unassign_skill_from_agent": {
|
|
742
|
+
const agent = AgentDB.findById(args.agent_id);
|
|
743
|
+
if (!agent) {
|
|
744
|
+
return { content: [{ type: "text", text: `Agent not found: ${args.agent_id}` }], isError: true };
|
|
745
|
+
}
|
|
746
|
+
const skills = agent.skills || [];
|
|
747
|
+
if (!skills.includes(args.skill_id)) {
|
|
748
|
+
return { content: [{ type: "text", text: `Skill is not assigned to this agent` }] };
|
|
749
|
+
}
|
|
750
|
+
AgentDB.update(args.agent_id, { skills: skills.filter((id: string) => id !== args.skill_id) });
|
|
751
|
+
return { content: [{ type: "text", text: `Removed skill from agent "${agent.name}". Restart the agent for changes to take effect.` }] };
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
case "delete_skill": {
|
|
755
|
+
const skill = SkillDB.findById(args.skill_id);
|
|
756
|
+
if (!skill) {
|
|
757
|
+
return { content: [{ type: "text", text: `Skill not found: ${args.skill_id}` }], isError: true };
|
|
758
|
+
}
|
|
759
|
+
// Unassign from all agents first
|
|
760
|
+
const agentsWithSkill = AgentDB.findBySkill(args.skill_id);
|
|
761
|
+
for (const agent of agentsWithSkill) {
|
|
762
|
+
const updated = (agent.skills || []).filter((id: string) => id !== args.skill_id);
|
|
763
|
+
AgentDB.update(agent.id, { skills: updated });
|
|
764
|
+
}
|
|
765
|
+
SkillDB.delete(args.skill_id);
|
|
766
|
+
return { content: [{ type: "text", text: `Skill "${skill.name}" deleted${agentsWithSkill.length > 0 ? ` (unassigned from ${agentsWithSkill.length} agent(s))` : ""}` }] };
|
|
767
|
+
}
|
|
768
|
+
|
|
416
769
|
default:
|
|
417
770
|
return { content: [{ type: "text", text: `Unknown tool: ${name}` }], isError: true };
|
|
418
771
|
}
|
|
@@ -460,7 +813,17 @@ export async function handlePlatformMcpRequest(req: Request): Promise<Response>
|
|
|
460
813
|
name: "apteva-platform",
|
|
461
814
|
version: "1.0.0",
|
|
462
815
|
},
|
|
463
|
-
instructions:
|
|
816
|
+
instructions: `This MCP server controls the Apteva AI agent management platform.
|
|
817
|
+
|
|
818
|
+
You can manage:
|
|
819
|
+
- AGENTS: Create, configure, start, stop, and delete AI agents. Each agent has a provider (LLM), model, system prompt, and optional features (memory, tasks, vision, MCP tools, files).
|
|
820
|
+
- PROJECTS: Organize agents into projects for grouping.
|
|
821
|
+
- MCP SERVERS: Tool integrations that give agents capabilities (web search, file access, APIs). Assign servers to agents.
|
|
822
|
+
- SKILLS: Reusable instruction sets that specialize agent behavior. Assign skills to agents.
|
|
823
|
+
- PROVIDERS: View which LLM providers have API keys configured.
|
|
824
|
+
|
|
825
|
+
Typical workflow: list_providers → create_agent → assign MCP servers/skills → start_agent.
|
|
826
|
+
Always use list_providers first to check which providers have API keys before creating agents.`,
|
|
464
827
|
};
|
|
465
828
|
break;
|
|
466
829
|
}
|
|
@@ -47,23 +47,31 @@ export async function handleMetaAgentRoutes(
|
|
|
47
47
|
name: "Apteva Assistant",
|
|
48
48
|
model: defaultModel,
|
|
49
49
|
provider: providerId,
|
|
50
|
-
system_prompt: `You are the Apteva Assistant, an AI that manages the Apteva agent platform.
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
- Create, configure, start, and
|
|
54
|
-
-
|
|
55
|
-
-
|
|
56
|
-
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
Use
|
|
65
|
-
|
|
66
|
-
|
|
50
|
+
system_prompt: `You are the Apteva Assistant, an AI that manages the Apteva agent platform. You have full control over the platform via your tools.
|
|
51
|
+
|
|
52
|
+
WHAT YOU CAN DO:
|
|
53
|
+
- **Agents**: Create, configure, start, stop, and delete AI agents
|
|
54
|
+
- **Projects**: Create projects and organize agents into them
|
|
55
|
+
- **MCP Servers**: Add tool integrations (HTTP, npm, pip) and assign them to agents
|
|
56
|
+
- **Skills**: List, enable/disable, and assign skills to agents
|
|
57
|
+
- **Providers**: Check which LLM providers have API keys configured
|
|
58
|
+
- **Communication**: Send messages to running agents
|
|
59
|
+
|
|
60
|
+
WORKFLOW FOR CREATING AGENTS:
|
|
61
|
+
1. Use list_providers to check which providers have API keys
|
|
62
|
+
2. Use create_agent with a provider that has a key, pick a model, write a good system prompt
|
|
63
|
+
3. Optionally assign MCP servers (for tools) and skills (for behavior)
|
|
64
|
+
4. Use start_agent to run it
|
|
65
|
+
|
|
66
|
+
AGENT FEATURES (enable when creating/updating):
|
|
67
|
+
- **memory**: Persistent memory across conversations (needs OpenAI key for embeddings)
|
|
68
|
+
- **tasks**: Scheduling and task tracking
|
|
69
|
+
- **vision**: Image and PDF understanding
|
|
70
|
+
- **mcp**: Required if assigning MCP servers — gives the agent tool-use capability
|
|
71
|
+
- **files**: File read/write in agent workspace
|
|
72
|
+
|
|
73
|
+
ALWAYS use your tools proactively. When a user says "create an agent", don't explain how — just do it. Confirm what you did after.
|
|
74
|
+
Be concise. Use markdown formatting.`,
|
|
67
75
|
features: {
|
|
68
76
|
memory: false,
|
|
69
77
|
tasks: false,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import React, { useState, useEffect, createContext, useContext, type ReactNode } from "react";
|
|
1
|
+
import React, { useState, useEffect, useMemo, createContext, useContext, type ReactNode } from "react";
|
|
2
2
|
import { Chat } from "@apteva/apteva-kit";
|
|
3
|
-
import { useAuth } from "../../context";
|
|
3
|
+
import { useAuth, useProjects } from "../../context";
|
|
4
4
|
|
|
5
5
|
interface MetaAgentStatus {
|
|
6
6
|
enabled: boolean;
|
|
@@ -129,10 +129,24 @@ export function MetaAgentButton() {
|
|
|
129
129
|
// Chat panel component - renders as a right-side drawer
|
|
130
130
|
export function MetaAgentPanel() {
|
|
131
131
|
const ctx = useMetaAgent();
|
|
132
|
+
const { currentProjectId, currentProject } = useProjects();
|
|
132
133
|
if (!ctx?.isAvailable || !ctx.isOpen) return null;
|
|
133
134
|
|
|
134
135
|
const { agent, isRunning, error, isStarting, startAgent, close } = ctx;
|
|
135
136
|
|
|
137
|
+
// Build context string for the meta agent
|
|
138
|
+
const chatContext = useMemo(() => {
|
|
139
|
+
const parts: string[] = [];
|
|
140
|
+
if (currentProject) {
|
|
141
|
+
parts.push(`Current project: "${currentProject.name}" (id: ${currentProject.id})`);
|
|
142
|
+
} else if (currentProjectId === "unassigned") {
|
|
143
|
+
parts.push("Viewing: unassigned agents (no project)");
|
|
144
|
+
} else {
|
|
145
|
+
parts.push("Viewing: All Projects");
|
|
146
|
+
}
|
|
147
|
+
return parts.join("\n");
|
|
148
|
+
}, [currentProjectId, currentProject]);
|
|
149
|
+
|
|
136
150
|
return (
|
|
137
151
|
<>
|
|
138
152
|
{/* Backdrop */}
|
|
@@ -166,6 +180,7 @@ export function MetaAgentPanel() {
|
|
|
166
180
|
placeholder="Ask me anything about Apteva..."
|
|
167
181
|
variant="terminal"
|
|
168
182
|
showHeader={false}
|
|
183
|
+
context={chatContext}
|
|
169
184
|
/>
|
|
170
185
|
) : (
|
|
171
186
|
<div className="flex-1 flex flex-col items-center justify-center p-6 text-center">
|