chat-agent-toolkit 1.2.1
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.md +234 -0
- package/package.json +101 -0
- package/src/config/config-manager.ts +319 -0
- package/src/config/config-types.ts +65 -0
- package/src/config/environment-variables.ts +8 -0
- package/src/config/index.ts +26 -0
- package/src/config/language-models-database.ts +1426 -0
- package/src/config/mcp-server-registry.ts +24 -0
- package/src/config/model-registry.ts +256 -0
- package/src/config/model-tester.ts +211 -0
- package/src/config/model-utils.ts +193 -0
- package/src/config/provider-ui-config.ts +196 -0
- package/src/connectors/composio.json +154 -0
- package/src/index.ts +22 -0
- package/src/memory/ARCHITECTURE.md +302 -0
- package/src/memory/MASTRA_INTEGRATION.md +106 -0
- package/src/memory/README.md +224 -0
- package/src/memory/agent-memory-manager.ts +416 -0
- package/src/memory/example.ts +343 -0
- package/src/memory/index.ts +47 -0
- package/src/memory/mastra-integration.ts +609 -0
- package/src/memory/storage/drizzle-storage.ts +205 -0
- package/src/memory/storage/in-memory-storage.ts +551 -0
- package/src/memory/storage/storage-interface.ts +68 -0
- package/src/memory/types.ts +125 -0
- package/src/models/providers.ts +5 -0
- package/src/models/registry.ts +4 -0
- package/src/models/types.ts +4 -0
- package/src/search.ts +5 -0
- package/src/tools/composio-mastra.ts +305 -0
- package/src/tools/composio-mcp.ts +205 -0
- package/src/tools/index.ts +13 -0
- package/src/tools/qwksearch-api-tools.ts +327 -0
- package/src/tools/search/doc-utils.ts +75 -0
- package/src/tools/search/document.ts +47 -0
- package/src/tools/search/index.ts +13 -0
- package/src/tools/search/link-summarizer.ts +112 -0
- package/src/tools/search/meta-search-types.ts +62 -0
- package/src/tools/search/metaSearchAgent.ts +454 -0
- package/src/tools/search/search-handlers.ts +85 -0
- package/src/tools/search/suggestionGeneratorAgent.ts +54 -0
- package/src/types.d.ts +137 -0
- package/src/utils/README.md +98 -0
- package/src/utils/chat-helpers.ts +18 -0
- package/src/utils/index.ts +2 -0
- package/src/utils/markdown-to-html.ts +53 -0
- package/src/utils/outputParser.ts +73 -0
- package/src/utils/provider-image-cropper.ts +130 -0
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memory System Types and Constants
|
|
3
|
+
*
|
|
4
|
+
* Defines interfaces and configuration for the memory management system
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Memory types for categorization
|
|
9
|
+
*/
|
|
10
|
+
export const MEMORY_TYPES = {
|
|
11
|
+
FACT: "fact",
|
|
12
|
+
CONVERSATION: "conversation",
|
|
13
|
+
PREFERENCE: "preference",
|
|
14
|
+
PERSONAL: "personal",
|
|
15
|
+
WORK: "work",
|
|
16
|
+
MANUAL: "manual",
|
|
17
|
+
} as const;
|
|
18
|
+
|
|
19
|
+
export type MemoryType = (typeof MEMORY_TYPES)[keyof typeof MEMORY_TYPES];
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Configuration constants for memory management
|
|
23
|
+
*/
|
|
24
|
+
export const MEMORY_CONFIG = {
|
|
25
|
+
DEFAULT_MAX_MEMORIES: 100,
|
|
26
|
+
DEFAULT_SUMMARY_THRESHOLD: 10,
|
|
27
|
+
DEFAULT_CACHE_EXPIRY: 5 * 60 * 1000, // 5 minutes
|
|
28
|
+
DEFAULT_BATCH_SIZE: 5,
|
|
29
|
+
DEFAULT_RELEVANCE_THRESHOLD: 0.3,
|
|
30
|
+
DEFAULT_IMPORTANCE_RANGE: { min: 0, max: 10 },
|
|
31
|
+
DEFAULT_RATE_LIMIT: { requests: 10, windowMs: 60000 },
|
|
32
|
+
DEFAULT_TIMEOUT: 30000, // 30 seconds
|
|
33
|
+
VECTOR_SEARCH_ENABLED: true,
|
|
34
|
+
AUTO_SUMMARIZATION_ENABLED: true,
|
|
35
|
+
} as const;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Memory record structure
|
|
39
|
+
*/
|
|
40
|
+
export interface MemoryRecord {
|
|
41
|
+
id: string;
|
|
42
|
+
user_id: string;
|
|
43
|
+
memory_type: MemoryType;
|
|
44
|
+
content: string;
|
|
45
|
+
importance: number;
|
|
46
|
+
access_count: number;
|
|
47
|
+
metadata?: Record<string, any>;
|
|
48
|
+
created_at: Date;
|
|
49
|
+
updated_at: Date;
|
|
50
|
+
relevance_score?: number;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Message structure for conversation tracking
|
|
55
|
+
*/
|
|
56
|
+
export interface Message {
|
|
57
|
+
role: "user" | "assistant";
|
|
58
|
+
content: string;
|
|
59
|
+
timestamp: number;
|
|
60
|
+
metadata?: Record<string, any>;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Memory search options
|
|
65
|
+
*/
|
|
66
|
+
export interface MemorySearchOptions {
|
|
67
|
+
minImportance?: number;
|
|
68
|
+
memoryType?: MemoryType;
|
|
69
|
+
includeMetadata?: boolean;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Memory update payload
|
|
74
|
+
*/
|
|
75
|
+
export interface MemoryUpdate {
|
|
76
|
+
importance?: number;
|
|
77
|
+
access_count?: number | { increment: number };
|
|
78
|
+
updated_at?: Date;
|
|
79
|
+
metadata?: Record<string, any>;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Memory context options
|
|
84
|
+
*/
|
|
85
|
+
export interface MemoryContextOptions {
|
|
86
|
+
maxMemories?: number;
|
|
87
|
+
minImportance?: number;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Performance metrics
|
|
92
|
+
*/
|
|
93
|
+
export interface MemoryMetrics {
|
|
94
|
+
cacheHits: number;
|
|
95
|
+
cacheMisses: number;
|
|
96
|
+
vectorSearches: number;
|
|
97
|
+
summarizations: number;
|
|
98
|
+
errors: number;
|
|
99
|
+
cacheSize: number;
|
|
100
|
+
recentMessagesCount: number;
|
|
101
|
+
isProcessing: boolean;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Memory initialization options
|
|
106
|
+
*/
|
|
107
|
+
export interface MemoryOptions {
|
|
108
|
+
maxMemories?: number;
|
|
109
|
+
summaryThreshold?: number;
|
|
110
|
+
cacheExpiry?: number;
|
|
111
|
+
batchSize?: number;
|
|
112
|
+
relevanceThreshold?: number;
|
|
113
|
+
enableVectorSearch?: boolean;
|
|
114
|
+
enableAutoSummarization?: boolean;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Extracted fact structure
|
|
119
|
+
*/
|
|
120
|
+
export interface ExtractedFact {
|
|
121
|
+
content: string;
|
|
122
|
+
importance?: number;
|
|
123
|
+
category?: MemoryType;
|
|
124
|
+
metadata?: Record<string, any>;
|
|
125
|
+
}
|
package/src/search.ts
ADDED
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Composio + Mastra Integration
|
|
3
|
+
*
|
|
4
|
+
* Connects Composio's MCP endpoint to Mastra agents.
|
|
5
|
+
* Composio provides the tools, Mastra provides the agent framework.
|
|
6
|
+
*
|
|
7
|
+
* Architecture:
|
|
8
|
+
* 1. Create Composio Tool Router session → Get MCP URL + headers
|
|
9
|
+
* 2. Configure Mastra MCPClient with URL + headers
|
|
10
|
+
* 3. Get tools with mcp.listTools() or mcp.listToolsets()
|
|
11
|
+
* 4. Create Mastra Agent with tools
|
|
12
|
+
* 5. Execute agent.generate() with multi-step tool calling
|
|
13
|
+
*
|
|
14
|
+
* @see https://composio.dev/toolkits/composio/framework/mastra-ai
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { Composio } from '@composio/core';
|
|
18
|
+
import { Agent } from '@mastra/core/agent';
|
|
19
|
+
import { MCPClient } from '@mastra/mcp';
|
|
20
|
+
import type { Tool } from '@mastra/core';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Configuration for Composio + Mastra integration
|
|
24
|
+
*/
|
|
25
|
+
export interface ComposioMastraConfig {
|
|
26
|
+
/** Composio API key */
|
|
27
|
+
composioApiKey: string;
|
|
28
|
+
/** User ID for scoping the session */
|
|
29
|
+
userId: string;
|
|
30
|
+
/** Toolkits to enable */
|
|
31
|
+
toolkits: string[];
|
|
32
|
+
/** Agent configuration */
|
|
33
|
+
agent: {
|
|
34
|
+
id: string;
|
|
35
|
+
name: string;
|
|
36
|
+
instructions: string;
|
|
37
|
+
model: any; // Mastra model instance (e.g., openai('gpt-4o'))
|
|
38
|
+
maxSteps?: number;
|
|
39
|
+
};
|
|
40
|
+
/** Whether to require approval before tool execution */
|
|
41
|
+
requireToolApproval?: boolean;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Composio + Mastra session manager
|
|
46
|
+
* Handles MCP connection lifecycle and agent creation
|
|
47
|
+
*/
|
|
48
|
+
export class ComposioMastraSession {
|
|
49
|
+
private composio: Composio;
|
|
50
|
+
private mcpClient: MCPClient | null = null;
|
|
51
|
+
private agent: Agent | null = null;
|
|
52
|
+
private sessionEndpoint: { url: string; headers: Record<string, string> } | null =
|
|
53
|
+
null;
|
|
54
|
+
|
|
55
|
+
constructor(private config: ComposioMastraConfig) {
|
|
56
|
+
this.composio = new Composio({
|
|
57
|
+
apiKey: config.composioApiKey,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Create Composio Tool Router session
|
|
63
|
+
* Returns MCP endpoint URL + auth headers
|
|
64
|
+
*/
|
|
65
|
+
private async createSession() {
|
|
66
|
+
if (this.sessionEndpoint) {
|
|
67
|
+
return this.sessionEndpoint;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Create Composio session with specified toolkits
|
|
71
|
+
const session = await this.composio.toolsets.create({
|
|
72
|
+
userId: this.config.userId,
|
|
73
|
+
toolkits: this.config.toolkits,
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
this.sessionEndpoint = {
|
|
77
|
+
url: session.mcp.url,
|
|
78
|
+
headers: {
|
|
79
|
+
'x-api-key': this.config.composioApiKey,
|
|
80
|
+
...session.mcp.headers,
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
return this.sessionEndpoint;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Get or create Mastra MCP client
|
|
89
|
+
* Connects to Composio's MCP endpoint via HTTP
|
|
90
|
+
*/
|
|
91
|
+
async getMCPClient(): Promise<MCPClient> {
|
|
92
|
+
if (this.mcpClient) {
|
|
93
|
+
return this.mcpClient;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const endpoint = await this.createSession();
|
|
97
|
+
|
|
98
|
+
// Create Mastra MCP client
|
|
99
|
+
this.mcpClient = new MCPClient({
|
|
100
|
+
id: `composio-${this.config.userId}`,
|
|
101
|
+
servers: {
|
|
102
|
+
composio: {
|
|
103
|
+
url: new URL(endpoint.url),
|
|
104
|
+
requestInit: {
|
|
105
|
+
headers: endpoint.headers,
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
return this.mcpClient;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Get tools from Composio MCP
|
|
116
|
+
* Use for static agent setup (same tools for all requests)
|
|
117
|
+
*/
|
|
118
|
+
async getTools(): Promise<Record<string, Tool>> {
|
|
119
|
+
const mcp = await this.getMCPClient();
|
|
120
|
+
return await mcp.listTools();
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Get toolsets from Composio MCP
|
|
125
|
+
* Use for dynamic per-request tool configuration
|
|
126
|
+
*/
|
|
127
|
+
async getToolsets() {
|
|
128
|
+
const mcp = await this.getMCPClient();
|
|
129
|
+
return await mcp.listToolsets();
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Create or get Mastra agent with Composio tools
|
|
134
|
+
* Agent is cached and reused across generate() calls
|
|
135
|
+
*/
|
|
136
|
+
async getAgent(): Promise<Agent> {
|
|
137
|
+
if (this.agent) {
|
|
138
|
+
return this.agent;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const tools = await this.getTools();
|
|
142
|
+
|
|
143
|
+
this.agent = new Agent({
|
|
144
|
+
id: this.config.agent.id,
|
|
145
|
+
name: this.config.agent.name,
|
|
146
|
+
instructions: this.config.agent.instructions,
|
|
147
|
+
model: this.config.agent.model,
|
|
148
|
+
tools,
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
return this.agent;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Execute agent with a prompt
|
|
156
|
+
* Handles multi-step tool calling automatically
|
|
157
|
+
*
|
|
158
|
+
* @param prompt - User prompt
|
|
159
|
+
* @param options - Generation options
|
|
160
|
+
* @returns Agent response with text and tool calls
|
|
161
|
+
*/
|
|
162
|
+
async generate(
|
|
163
|
+
prompt: string,
|
|
164
|
+
options?: {
|
|
165
|
+
maxSteps?: number;
|
|
166
|
+
context?: Record<string, any>;
|
|
167
|
+
}
|
|
168
|
+
) {
|
|
169
|
+
const agent = await this.getAgent();
|
|
170
|
+
|
|
171
|
+
return await agent.generate(prompt, {
|
|
172
|
+
maxSteps: options?.maxSteps || this.config.agent.maxSteps || 5,
|
|
173
|
+
...(options?.context && { context: options.context }),
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Clean up MCP connection and agent
|
|
179
|
+
* Call when done with the session
|
|
180
|
+
*/
|
|
181
|
+
async cleanup() {
|
|
182
|
+
if (this.mcpClient) {
|
|
183
|
+
await this.mcpClient.disconnect();
|
|
184
|
+
this.mcpClient = null;
|
|
185
|
+
}
|
|
186
|
+
this.agent = null;
|
|
187
|
+
this.sessionEndpoint = null;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Quick helper to create a Composio + Mastra agent
|
|
193
|
+
* For one-off usage without session management
|
|
194
|
+
*
|
|
195
|
+
* @example
|
|
196
|
+
* ```ts
|
|
197
|
+
* const result = await createComposioMastraAgent({
|
|
198
|
+
* composioApiKey: process.env.COMPOSIO_API_KEY!,
|
|
199
|
+
* userId: 'user-123',
|
|
200
|
+
* toolkits: ['GMAIL', 'SLACK'],
|
|
201
|
+
* agent: {
|
|
202
|
+
* id: 'email-agent',
|
|
203
|
+
* name: 'Email Assistant',
|
|
204
|
+
* instructions: 'Help with email tasks',
|
|
205
|
+
* model: openai('gpt-4o'),
|
|
206
|
+
* },
|
|
207
|
+
* }).generate('Check my unread emails');
|
|
208
|
+
* ```
|
|
209
|
+
*/
|
|
210
|
+
export async function createComposioMastraAgent(config: ComposioMastraConfig) {
|
|
211
|
+
const session = new ComposioMastraSession(config);
|
|
212
|
+
await session.getAgent(); // Initialize
|
|
213
|
+
return session;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Create Mastra agent with dynamic per-request toolsets
|
|
218
|
+
* Better for multi-user scenarios where tools vary per request
|
|
219
|
+
*
|
|
220
|
+
* @example
|
|
221
|
+
* ```ts
|
|
222
|
+
* const agent = await createDynamicComposioAgent({
|
|
223
|
+
* composioApiKey: process.env.COMPOSIO_API_KEY!,
|
|
224
|
+
* agent: {
|
|
225
|
+
* id: 'dynamic-agent',
|
|
226
|
+
* name: 'Dynamic Assistant',
|
|
227
|
+
* instructions: 'Use available tools',
|
|
228
|
+
* model: openai('gpt-4o'),
|
|
229
|
+
* },
|
|
230
|
+
* });
|
|
231
|
+
*
|
|
232
|
+
* // Each request can have different userId/toolkits
|
|
233
|
+
* const result = await agent.generate({
|
|
234
|
+
* userId: 'user-123',
|
|
235
|
+
* toolkits: ['GMAIL'],
|
|
236
|
+
* prompt: 'Check emails',
|
|
237
|
+
* });
|
|
238
|
+
* ```
|
|
239
|
+
*/
|
|
240
|
+
export async function createDynamicComposioAgent(config: {
|
|
241
|
+
composioApiKey: string;
|
|
242
|
+
agent: {
|
|
243
|
+
id: string;
|
|
244
|
+
name: string;
|
|
245
|
+
instructions: string;
|
|
246
|
+
model: any;
|
|
247
|
+
maxSteps?: number;
|
|
248
|
+
};
|
|
249
|
+
}) {
|
|
250
|
+
const composio = new Composio({
|
|
251
|
+
apiKey: config.composioApiKey,
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
return {
|
|
255
|
+
async generate(params: {
|
|
256
|
+
userId: string;
|
|
257
|
+
toolkits: string[];
|
|
258
|
+
prompt: string;
|
|
259
|
+
maxSteps?: number;
|
|
260
|
+
}) {
|
|
261
|
+
// Create session for this user/toolkits
|
|
262
|
+
const session = await composio.toolsets.create({
|
|
263
|
+
userId: params.userId,
|
|
264
|
+
toolkits: params.toolkits,
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
// Connect MCP client
|
|
268
|
+
const mcp = new MCPClient({
|
|
269
|
+
id: `composio-${params.userId}`,
|
|
270
|
+
servers: {
|
|
271
|
+
composio: {
|
|
272
|
+
url: new URL(session.mcp.url),
|
|
273
|
+
requestInit: {
|
|
274
|
+
headers: {
|
|
275
|
+
'x-api-key': config.composioApiKey,
|
|
276
|
+
...session.mcp.headers,
|
|
277
|
+
},
|
|
278
|
+
},
|
|
279
|
+
},
|
|
280
|
+
},
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
try {
|
|
284
|
+
// Get toolsets for this request
|
|
285
|
+
const toolsets = await mcp.listToolsets();
|
|
286
|
+
|
|
287
|
+
// Create agent with dynamic toolsets
|
|
288
|
+
const agent = new Agent({
|
|
289
|
+
id: config.agent.id,
|
|
290
|
+
name: config.agent.name,
|
|
291
|
+
instructions: config.agent.instructions,
|
|
292
|
+
model: config.agent.model,
|
|
293
|
+
toolsets,
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
// Execute
|
|
297
|
+
return await agent.generate(params.prompt, {
|
|
298
|
+
maxSteps: params.maxSteps || config.agent.maxSteps || 5,
|
|
299
|
+
});
|
|
300
|
+
} finally {
|
|
301
|
+
await mcp.disconnect();
|
|
302
|
+
}
|
|
303
|
+
},
|
|
304
|
+
};
|
|
305
|
+
}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Composio MCP Integration for AI SDK v5
|
|
3
|
+
*
|
|
4
|
+
* Composio provides dynamic MCP endpoints through sessions/Tool Router.
|
|
5
|
+
* This module creates MCP clients connected to Composio's HTTP endpoints,
|
|
6
|
+
* fetches available tools, and passes them to AI SDK models.
|
|
7
|
+
*
|
|
8
|
+
* Architecture:
|
|
9
|
+
* 1. Create Composio session → Get MCP URL + headers
|
|
10
|
+
* 2. Connect with createMCPClient (HTTP transport)
|
|
11
|
+
* 3. Fetch tools with client.tools()
|
|
12
|
+
* 4. Pass to streamText/generateText
|
|
13
|
+
*
|
|
14
|
+
* @see https://composio.dev/toolkits/ai_ml_api/framework/ai-sdk
|
|
15
|
+
* @see https://ai-sdk.dev/docs/ai-sdk-core/mcp-tools
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { Composio } from '@composio/core';
|
|
19
|
+
import { createMCPClient } from '@ai-sdk/mcp';
|
|
20
|
+
import type { MCPClient } from '@ai-sdk/mcp';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Configuration for Composio MCP session
|
|
24
|
+
*/
|
|
25
|
+
export interface ComposioMCPConfig {
|
|
26
|
+
/** Composio API key */
|
|
27
|
+
apiKey: string;
|
|
28
|
+
/** User ID to scope the session */
|
|
29
|
+
userId: string;
|
|
30
|
+
/** Toolkits to enable (e.g., ['GMAIL', 'NOTION', 'SLACK']) */
|
|
31
|
+
toolkits: string[];
|
|
32
|
+
/** Optional: Additional MCP headers (e.g., x-api-key if org requires it) */
|
|
33
|
+
additionalHeaders?: Record<string, string>;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Composio MCP session wrapper
|
|
38
|
+
* Manages the lifecycle of MCP client connections to Composio
|
|
39
|
+
*/
|
|
40
|
+
export class ComposioMCPSession {
|
|
41
|
+
private composio: Composio;
|
|
42
|
+
private client: MCPClient | null = null;
|
|
43
|
+
private mcpEndpoint: { url: string; headers: Record<string, string> } | null = null;
|
|
44
|
+
|
|
45
|
+
constructor(private config: ComposioMCPConfig) {
|
|
46
|
+
this.composio = new Composio({
|
|
47
|
+
apiKey: config.apiKey,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Create Composio Tool Router session and get MCP endpoint
|
|
53
|
+
* This returns the HTTP URL and auth headers for the MCP server
|
|
54
|
+
*/
|
|
55
|
+
private async getOrCreateEndpoint() {
|
|
56
|
+
if (this.mcpEndpoint) {
|
|
57
|
+
return this.mcpEndpoint;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Create dynamic Composio session with specified toolkits
|
|
61
|
+
const session = await this.composio.toolkits.authorize({
|
|
62
|
+
userId: this.config.userId,
|
|
63
|
+
toolkits: this.config.toolkits,
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// Extract MCP endpoint info
|
|
67
|
+
this.mcpEndpoint = {
|
|
68
|
+
url: session.mcp.url,
|
|
69
|
+
headers: {
|
|
70
|
+
...session.mcp.headers,
|
|
71
|
+
...this.config.additionalHeaders,
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
return this.mcpEndpoint;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Get or create the MCP client connection
|
|
80
|
+
* Uses HTTP transport as recommended by Composio
|
|
81
|
+
*/
|
|
82
|
+
async getClient(): Promise<MCPClient> {
|
|
83
|
+
if (this.client) {
|
|
84
|
+
return this.client;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const endpoint = await this.getOrCreateEndpoint();
|
|
88
|
+
|
|
89
|
+
// Connect to Composio MCP endpoint via HTTP
|
|
90
|
+
this.client = await createMCPClient({
|
|
91
|
+
transport: {
|
|
92
|
+
type: 'http',
|
|
93
|
+
url: endpoint.url,
|
|
94
|
+
headers: endpoint.headers,
|
|
95
|
+
redirect: 'error',
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
return this.client;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Get all available tools from Composio MCP
|
|
104
|
+
* These tools can be passed directly to streamText/generateText
|
|
105
|
+
*
|
|
106
|
+
* @returns Tools object compatible with AI SDK
|
|
107
|
+
*/
|
|
108
|
+
async getTools() {
|
|
109
|
+
const client = await this.getClient();
|
|
110
|
+
return await client.tools();
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Close the MCP connection
|
|
115
|
+
* Should be called after request completion or in finally block
|
|
116
|
+
*/
|
|
117
|
+
async close() {
|
|
118
|
+
if (this.client) {
|
|
119
|
+
await this.client.close();
|
|
120
|
+
this.client = null;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Get list of available toolkits from Composio
|
|
126
|
+
* Useful for discovering what integrations are available
|
|
127
|
+
*/
|
|
128
|
+
static async listAvailableToolkits(apiKey: string): Promise<string[]> {
|
|
129
|
+
const composio = new Composio({ apiKey });
|
|
130
|
+
const toolkits = await composio.toolkits.list();
|
|
131
|
+
return toolkits.map((t) => t.name);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Check if a user has authenticated a specific toolkit
|
|
136
|
+
* Returns true if the user can access the toolkit's tools
|
|
137
|
+
*/
|
|
138
|
+
async isToolkitAuthenticated(toolkit: string): Promise<boolean> {
|
|
139
|
+
try {
|
|
140
|
+
const integrations = await this.composio.integrations.list({
|
|
141
|
+
appName: toolkit,
|
|
142
|
+
});
|
|
143
|
+
return integrations.length > 0;
|
|
144
|
+
} catch {
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Helper function to create a one-shot Composio MCP session
|
|
152
|
+
* For quick tool usage without managing session lifecycle
|
|
153
|
+
*
|
|
154
|
+
* @example
|
|
155
|
+
* ```ts
|
|
156
|
+
* const tools = await getComposioTools({
|
|
157
|
+
* apiKey: process.env.COMPOSIO_API_KEY!,
|
|
158
|
+
* userId: 'user-123',
|
|
159
|
+
* toolkits: ['GMAIL', 'SLACK'],
|
|
160
|
+
* });
|
|
161
|
+
*
|
|
162
|
+
* const result = await generateText({
|
|
163
|
+
* model: openai('gpt-4o'),
|
|
164
|
+
* prompt: 'Check my unread emails',
|
|
165
|
+
* tools,
|
|
166
|
+
* });
|
|
167
|
+
* ```
|
|
168
|
+
*/
|
|
169
|
+
export async function getComposioTools(config: ComposioMCPConfig) {
|
|
170
|
+
const session = new ComposioMCPSession(config);
|
|
171
|
+
try {
|
|
172
|
+
return await session.getTools();
|
|
173
|
+
} finally {
|
|
174
|
+
await session.close();
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Create a reusable Composio MCP session
|
|
180
|
+
* Better for multiple requests with the same toolkits
|
|
181
|
+
*
|
|
182
|
+
* @example
|
|
183
|
+
* ```ts
|
|
184
|
+
* const session = await createComposioSession({
|
|
185
|
+
* apiKey: process.env.COMPOSIO_API_KEY!,
|
|
186
|
+
* userId: 'user-123',
|
|
187
|
+
* toolkits: ['GMAIL', 'NOTION'],
|
|
188
|
+
* });
|
|
189
|
+
*
|
|
190
|
+
* try {
|
|
191
|
+
* const tools = await session.getTools();
|
|
192
|
+
* const result = await streamText({ model, messages, tools });
|
|
193
|
+
* } finally {
|
|
194
|
+
* await session.close();
|
|
195
|
+
* }
|
|
196
|
+
* ```
|
|
197
|
+
*/
|
|
198
|
+
export async function createComposioSession(
|
|
199
|
+
config: ComposioMCPConfig
|
|
200
|
+
): Promise<ComposioMCPSession> {
|
|
201
|
+
const session = new ComposioMCPSession(config);
|
|
202
|
+
// Pre-initialize the connection
|
|
203
|
+
await session.getClient();
|
|
204
|
+
return session;
|
|
205
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Agent Tools Module
|
|
3
|
+
*
|
|
4
|
+
* Exports tool definitions for QwkSearch API integration including web search,
|
|
5
|
+
* content extraction, and AI response generation. Tools are automatically
|
|
6
|
+
* attached to agents when declared in prompt templates.
|
|
7
|
+
*
|
|
8
|
+
* @module tools
|
|
9
|
+
* @author ai-research-agent contributors
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
export { AGENT_TOOLS } from "./qwksearch-api-tools";
|
|
13
|
+
export * from "./search";
|