@kasarlabs/ask-starknet-mcp 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.
Files changed (40) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +197 -0
  3. package/build/graph/agents/prompts.d.ts +9 -0
  4. package/build/graph/agents/prompts.d.ts.map +1 -0
  5. package/build/graph/agents/prompts.js +25 -0
  6. package/build/graph/agents/prompts.js.map +1 -0
  7. package/build/graph/agents/selector.d.ts +9 -0
  8. package/build/graph/agents/selector.d.ts.map +1 -0
  9. package/build/graph/agents/selector.js +60 -0
  10. package/build/graph/agents/selector.js.map +1 -0
  11. package/build/graph/agents/specialized.d.ts +6 -0
  12. package/build/graph/agents/specialized.d.ts.map +1 -0
  13. package/build/graph/agents/specialized.js +71 -0
  14. package/build/graph/agents/specialized.js.map +1 -0
  15. package/build/graph/graph.d.ts +66 -0
  16. package/build/graph/graph.d.ts.map +1 -0
  17. package/build/graph/graph.js +31 -0
  18. package/build/graph/graph.js.map +1 -0
  19. package/build/graph/mcps/interfaces.d.ts +27 -0
  20. package/build/graph/mcps/interfaces.d.ts.map +1 -0
  21. package/build/graph/mcps/interfaces.js +2 -0
  22. package/build/graph/mcps/interfaces.js.map +1 -0
  23. package/build/graph/mcps/utilities.d.ts +15 -0
  24. package/build/graph/mcps/utilities.d.ts.map +1 -0
  25. package/build/graph/mcps/utilities.js +76 -0
  26. package/build/graph/mcps/utilities.js.map +1 -0
  27. package/build/index.d.ts +32 -0
  28. package/build/index.d.ts.map +1 -0
  29. package/build/index.js +143 -0
  30. package/build/index.js.map +1 -0
  31. package/build/utils/llm.d.ts +4 -0
  32. package/build/utils/llm.d.ts.map +1 -0
  33. package/build/utils/llm.js +30 -0
  34. package/build/utils/llm.js.map +1 -0
  35. package/build/utils/logger.d.ts +6 -0
  36. package/build/utils/logger.d.ts.map +1 -0
  37. package/build/utils/logger.js +14 -0
  38. package/build/utils/logger.js.map +1 -0
  39. package/mcps.json +436 -0
  40. package/package.json +57 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Kasar Labs
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.
package/README.md ADDED
@@ -0,0 +1,197 @@
1
+ <div align="center">
2
+ <img src="https://github.com/KasarLabs/brand/blob/main/projects/ask-starknet/ask_full_logo_grey_alpha.png?raw=true" width="200" alt="Ask Starknet Logo">
3
+
4
+ </div>
5
+
6
+ # Ask Starknet MCP Server
7
+
8
+ A unified Model Context Protocol (MCP) server that provides AI-powered routing to specialized Starknet MCP servers. Instead of manually selecting which MCP server to use, Ask Starknet intelligently analyzes your requests and routes them to the appropriate specialized server automatically.
9
+
10
+ ## Quick Start
11
+
12
+ ```bash
13
+ npx -y @kasarlabs/ask-starknet-mcp
14
+ ```
15
+
16
+ ## Configuration
17
+
18
+ ### Required Environment Variables
19
+
20
+ **At least one LLM API key is required:**
21
+
22
+ - `ANTHROPIC_API_KEY`: Claude models (recommended)
23
+ - `GEMINI_API_KEY`: Google Gemini models
24
+ - `OPENAI_API_KEY`: OpenAI models
25
+
26
+ **Optional:**
27
+
28
+ - `MODEL_NAME`: Specify model (defaults: `claude-sonnet-4-20250514`, `gemini-2.5-flash`, or `gpt-4o-mini`)
29
+
30
+ ### Optional MCP-Specific Environment Variables
31
+
32
+ Ask Starknet routes to specialized MCP servers based on your requests. **Only set the environment variables for the MCPs you want to use:**
33
+
34
+ #### For Blockchain Operations
35
+
36
+ - `STARKNET_RPC_URL`: Starknet RPC endpoint
37
+ - `STARKNET_ACCOUNT_ADDRESS`: Your account address (for signing transactions)
38
+ - `STARKNET_PRIVATE_KEY`: Your private key (for signing transactions)
39
+
40
+ Used by: **ERC20**, **ERC721**, **AVNU**, **Contract**, **Transaction**, **Ekubo**, **Endurfi**, **Fibrous**, **Opus**, **Unruggable**, **Vesu**
41
+
42
+ #### For Wallet Creation
43
+
44
+ - `STARKNET_RPC_URL`: Starknet RPC endpoint
45
+
46
+ Used by: **Argent**, **Braavos**, **OKX**, **OpenZeppelin**
47
+
48
+ #### For Blockchain Data Queries
49
+
50
+ - `STARKNET_RPC_URL`: Starknet RPC endpoint
51
+
52
+ Used by: **Starknet RPC**
53
+
54
+ #### For Perpetuals Trading
55
+
56
+ - `EXTENDED_API_KEY`: Your Extended API key
57
+ - `EXTENDED_API_URL`: Extended API endpoint
58
+ - `EXTENDED_PRIVATE_KEY`: Your Stark private key for Extended
59
+
60
+ Used by: **Extended**
61
+
62
+ #### For AI Development Assistant
63
+
64
+ - `CAIRO_CODER_API_KEY`: Your Cairo Coder API key
65
+
66
+ Used by: **Cairo Coder**
67
+
68
+ #### For Pixel Art
69
+
70
+ - `STARKNET_RPC_URL`, `STARKNET_ACCOUNT_ADDRESS`, `STARKNET_PRIVATE_KEY`
71
+ - `PATH_UPLOAD_DIR`: Upload directory path
72
+ - `SECRET_PHRASE`: Secret phrase for authentication
73
+
74
+ Used by: **Artpeace**
75
+
76
+ #### For Cairo Development
77
+
78
+ No additional environment variables needed for: **Scarb**
79
+
80
+ ### MCP Client Setup
81
+
82
+ **Minimal setup** (LLM + read-only operations):
83
+
84
+ ```json
85
+ {
86
+ "mcpServers": {
87
+ "ask-starknet": {
88
+ "command": "npx",
89
+ "args": ["-y", "@kasarlabs/ask-starknet-mcp"],
90
+ "env": {
91
+ "ANTHROPIC_API_KEY": "sk-...",
92
+ "STARKNET_RPC_URL": "https://your-rpc-url"
93
+ }
94
+ }
95
+ }
96
+ }
97
+ ```
98
+
99
+ **With specialized MCPs** (e.g., you need Extended, Cairo Coder, ERC20 MCP...)
100
+
101
+ ```json
102
+ {
103
+ "mcpServers": {
104
+ "ask-starknet": {
105
+ "command": "npx",
106
+ "args": ["-y", "@kasarlabs/ask-starknet-mcp"],
107
+ "env": {
108
+ "ANTHROPIC_API_KEY": "sk-...",
109
+ "STARKNET_RPC_URL": "https://your-rpc-url",
110
+ "STARKNET_ACCOUNT_ADDRESS": "0x...",
111
+ "STARKNET_PRIVATE_KEY": "0x...",
112
+ "EXTENDED_API_KEY": "your-extended-key",
113
+ "EXTENDED_API_URL": "https://api.starknet.extended.exchange",
114
+ "EXTENDED_PRIVATE_KEY": "0x...",
115
+ "CAIRO_CODER_API_KEY": "your-cairo-coder-key"
116
+ }
117
+ }
118
+ }
119
+ }
120
+ ```
121
+
122
+ ## Available Tool
123
+
124
+ ### ask_starknet
125
+
126
+ Performs any Starknet-related action by intelligently routing to specialized MCP servers.
127
+
128
+ **Parameters:**
129
+
130
+ - `userInput` (string, required): Description of the Starknet action you want to perform
131
+
132
+ **Examples:**
133
+
134
+ ```typescript
135
+ { "userInput": "Transfer 100 USDC to 0x123..." }
136
+ { "userInput": "Swap 1 ETH for USDC on AVNU" }
137
+ { "userInput": "Open a long position on ETH/USD with 5x leverage on Extended" }
138
+ { "userInput": "Transfer my NFT #42 from collection 0xabc... to 0xdef..." }
139
+ { "userInput": "How do I implement an ERC20 token in Cairo?" }
140
+ ```
141
+
142
+ ## What You Can Do
143
+
144
+ Ask Starknet automatically routes your requests to the appropriate specialized MCP servers:
145
+
146
+ ### Wallets & Accounts
147
+
148
+ - **Argent**, **Braavos**, **OKX**, **OpenZeppelin**: Create and deploy wallet accounts
149
+
150
+ ### DeFi Protocols
151
+
152
+ - **AVNU**: DEX aggregator and token swaps
153
+ - **Ekubo**: Concentrated liquidity AMM, swaps, and liquidity provision
154
+ - **Endurfi**: Liquid staking (xSTRK, xyWBTC, xytBTC, xyLBTC)
155
+ - **Extended**: Perpetuals trading, derivatives, position management
156
+ - **Fibrous**: Multi-DEX swap routing for optimal prices
157
+ - **Opus**: Collateralized debt positions (Troves) and CASH borrowing
158
+ - **Vesu**: Lending, borrowing, and yield farming
159
+ - **Unruggable**: Memecoin creation and liquidity locking
160
+
161
+ ### Blockchain Operations
162
+
163
+ - **ERC20**: Token transfers, approvals, balances, deployment
164
+ - **ERC721**: NFT transfers, approvals, metadata, deployment
165
+ - **Transaction**: Transaction simulation and management
166
+ - **Starknet RPC**: Blockchain data queries and on-chain information
167
+
168
+ ### Development Tools
169
+
170
+ - **Scarb**: Cairo project initialization, compilation, execution, proving
171
+ - **Contract**: Smart contract declaration and deployment
172
+ - **Cairo Coder**: AI-powered Cairo development assistance and Starknet knowledge
173
+
174
+ ### Special
175
+
176
+ - **Artpeace**: Collaborative pixel art on Starknet canvas
177
+
178
+ ## How It Works
179
+
180
+ Ask Starknet uses an AI-powered routing system that:
181
+
182
+ 1. Analyzes your natural language request
183
+ 2. Determines which specialized MCP server(s) to use
184
+ 3. Routes the request with appropriate parameters
185
+ 4. Returns the result in a structured format
186
+
187
+ No need to remember which MCP server handles what - just describe what you want to do!
188
+
189
+ ## License
190
+
191
+ MIT
192
+
193
+ ## Support
194
+
195
+ - GitHub Issues: [Create an issue](https://github.com/kasarlabs/ask-starknet/issues)
196
+ - Documentation: [docs.kasar.io](https://docs.kasar.io)
197
+ - MCP Documentation: [Model Context Protocol](https://modelcontextprotocol.io/)
@@ -0,0 +1,9 @@
1
+ interface SpecializedPromptInfo {
2
+ agentName: string;
3
+ expertise: string;
4
+ tools: string[];
5
+ description: string;
6
+ }
7
+ export declare const specializedPrompt: (info: SpecializedPromptInfo) => string;
8
+ export {};
9
+ //# sourceMappingURL=prompts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../../src/graph/agents/prompts.ts"],"names":[],"mappings":"AAAA,UAAU,qBAAqB;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,eAAO,MAAM,iBAAiB,GAAI,MAAM,qBAAqB,KAAG,MAwB/D,CAAC"}
@@ -0,0 +1,25 @@
1
+ export const specializedPrompt = (info) => {
2
+ const toolsList = info.tools.map((tool) => ` - ${tool}`).join('\n');
3
+ return `You are a specialized MCP (Model Context Protocol) agent for ${info.agentName} on Starknet.
4
+
5
+ ## Description of ${info.agentName}
6
+ ${info.description}
7
+
8
+ ## Your Expertise
9
+ ${info.expertise}
10
+
11
+ ## Available Tools
12
+ You have access to the following MCP tools:
13
+ ${toolsList}
14
+
15
+ ## Instructions
16
+ 1. **Tool Selection**: Analyze the user's request and select the most appropriate tool from your available tools
17
+ 3. **Parameters**: Ensure all required parameters are present before calling a tool
18
+ 4. **Error Handling**: If a tool call fails, explain the error clearly to the user
19
+ 5. **Scope**: Only handle requests within your domain (${info.expertise})
20
+ 6. **Response Format**: Provide clear, concise responses with relevant transaction hashes or data when applicable
21
+
22
+ ## Context
23
+ This is a single-turn interaction. After you execute a tool and provide the result, the MCP client will decide if further actions are needed.`;
24
+ };
25
+ //# sourceMappingURL=prompts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../../src/graph/agents/prompts.ts"],"names":[],"mappings":"AAOA,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,IAA2B,EAAU,EAAE;IACvE,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAErE,OAAO,gEAAgE,IAAI,CAAC,SAAS;;oBAEnE,IAAI,CAAC,SAAS;EAChC,IAAI,CAAC,WAAW;;;EAGhB,IAAI,CAAC,SAAS;;;;EAId,SAAS;;;;;;yDAM8C,IAAI,CAAC,SAAS;;;;8IAIuE,CAAC;AAC/I,CAAC,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { GraphAnnotation } from '../graph.js';
2
+ export declare const selectorAgent: (state: typeof GraphAnnotation.State) => Promise<{
3
+ next: any;
4
+ routingInfo: {
5
+ reasoning: any;
6
+ timestamp: string;
7
+ };
8
+ }>;
9
+ //# sourceMappingURL=selector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selector.d.ts","sourceRoot":"","sources":["../../../src/graph/agents/selector.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAU9C,eAAO,MAAM,aAAa,GAAU,OAAO,OAAO,eAAe,CAAC,KAAK;;;;;;EA2DtE,CAAC"}
@@ -0,0 +1,60 @@
1
+ import { END } from '@langchain/langgraph';
2
+ import { z } from 'zod';
3
+ import { AvailableAgents, getMCPDescription } from '../mcps/utilities.js';
4
+ import { logger } from '../../utils/logger.js';
5
+ import { createLLM } from '../../utils/llm.js';
6
+ const selectorOutputSchema = z.object({
7
+ selectedAgent: z.enum([END, ...AvailableAgents]),
8
+ reasoning: z.string().describe('Why this agent was chosen'),
9
+ });
10
+ export const selectorAgent = async (state) => {
11
+ const lastMessage = state.messages[state.messages.length - 1];
12
+ const userInput = lastMessage.content;
13
+ const agentDescriptions = AvailableAgents.map((agent) => `- ${agent}: ${getMCPDescription(agent)}`).join('\n');
14
+ const systemPrompt = `You are a supervisor that routes requests to specialized agents.
15
+
16
+ Available agents:
17
+ ${agentDescriptions}
18
+
19
+ Instructions:
20
+ - Analyze the user's request
21
+ - If the user's original request has been COMPLETED by a previous agent response, choose "__end__"
22
+ - If a previous agent has already provided a complete answer or completed the requested action, choose "__end__"
23
+ - Only choose a specialized agent if the request is NEW or INCOMPLETE
24
+ - If no agent can handle the request, choose "__end__"
25
+
26
+
27
+ IMPORTANT: Look at the conversation history. If an agent has already successfully completed the user's request (like creating an account, providing information, etc.), you MUST choose "__end__" to stop the conversation.
28
+
29
+ Respond with the exact name of the chosen agent or "__end__".`;
30
+ const conversationHistory = state.messages
31
+ .map((msg, idx) => {
32
+ const role = msg.name || (idx === 0 ? 'user' : 'assistant');
33
+ const content = typeof msg.content === 'string'
34
+ ? msg.content.substring(0, 500)
35
+ : JSON.stringify(msg.content).substring(0, 500);
36
+ return `[${role}]: ${content}`;
37
+ })
38
+ .join('\n\n');
39
+ const model = createLLM(state.mcpEnvironment);
40
+ const structuredModel = model.withStructuredOutput(selectorOutputSchema);
41
+ const response = await structuredModel.invoke([
42
+ { role: 'system', content: systemPrompt },
43
+ {
44
+ role: 'user',
45
+ content: `Conversation history:\n${conversationHistory}\n\nOriginal user request: "${state.messages[0].content}"\n\nCurrent message: "${userInput}"\n\nHas the original request been completed? If yes, choose "__end__".`,
46
+ },
47
+ ]);
48
+ logger.error(`Routing decision`, {
49
+ selectedAgent: response.selectedAgent,
50
+ reasoning: response.reasoning,
51
+ });
52
+ return {
53
+ next: response.selectedAgent,
54
+ routingInfo: {
55
+ reasoning: response.reasoning,
56
+ timestamp: new Date().toISOString(),
57
+ },
58
+ };
59
+ };
60
+ //# sourceMappingURL=selector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selector.js","sourceRoot":"","sources":["../../../src/graph/agents/selector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,sBAAsB,CAAC;AAC3C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAC1E,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE/C,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IACpC,aAAa,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,GAAG,eAAe,CAA0B,CAAC;IACzE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,2BAA2B,CAAC;CAC5D,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,EAAE,KAAmC,EAAE,EAAE;IACzE,MAAM,WAAW,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC9D,MAAM,SAAS,GAAG,WAAW,CAAC,OAAO,CAAC;IAEtC,MAAM,iBAAiB,GAAG,eAAe,CAAC,GAAG,CAC3C,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,KAAK,iBAAiB,CAAC,KAAK,CAAC,EAAE,CACrD,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEb,MAAM,YAAY,GAAG;;;EAGrB,iBAAiB;;;;;;;;;;;;8DAY2C,CAAC;IAG7D,MAAM,mBAAmB,GAAG,KAAK,CAAC,QAAQ;SACvC,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QAChB,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;QAC5D,MAAM,OAAO,GACX,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ;YAC7B,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC;YAC/B,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QACpD,OAAO,IAAI,IAAI,MAAM,OAAO,EAAE,CAAC;IACjC,CAAC,CAAC;SACD,IAAI,CAAC,MAAM,CAAC,CAAC;IAEhB,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;IAC9C,MAAM,eAAe,GAAG,KAAK,CAAC,oBAAoB,CAAC,oBAAoB,CAAC,CAAC;IACzE,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,MAAM,CAAC;QAC5C,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE;QACzC;YACE,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE,0BAA0B,mBAAmB,+BAA+B,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,0BAA0B,SAAS,yEAAyE;SAC3N;KACF,CAAC,CAAC;IAEH,MAAM,CAAC,KAAK,CAAC,kBAAkB,EAAE;QAC/B,aAAa,EAAE,QAAQ,CAAC,aAAa;QACrC,SAAS,EAAE,QAAQ,CAAC,SAAS;KAC9B,CAAC,CAAC;IAEH,OAAO;QACL,IAAI,EAAE,QAAQ,CAAC,aAAa;QAC5B,WAAW,EAAE;YACX,SAAS,EAAE,QAAQ,CAAC,SAAS;YAC7B,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACpC;KACF,CAAC;AACJ,CAAC,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { HumanMessage } from '@langchain/core/messages';
2
+ import { GraphAnnotation } from '../graph.js';
3
+ export declare const specializedNode: (state: typeof GraphAnnotation.State) => Promise<{
4
+ messages: HumanMessage[];
5
+ }>;
6
+ //# sourceMappingURL=specialized.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"specialized.d.ts","sourceRoot":"","sources":["../../../src/graph/agents/specialized.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAiB,MAAM,0BAA0B,CAAC;AAIvE,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAiC9C,eAAO,MAAM,eAAe,GAAU,OAAO,OAAO,eAAe,CAAC,KAAK;;EA0DxE,CAAC"}
@@ -0,0 +1,71 @@
1
+ import { MultiServerMCPClient } from '@langchain/mcp-adapters';
2
+ import { HumanMessage, SystemMessage } from '@langchain/core/messages';
3
+ import { ToolNode } from '@langchain/langgraph/prebuilt';
4
+ import { getMCPClientConfig, getMCPPromptInfo } from '../mcps/utilities.js';
5
+ import { logger } from '../../utils/logger.js';
6
+ import { createLLM } from '../../utils/llm.js';
7
+ import { specializedPrompt } from './prompts.js';
8
+ async function specializedAgent(mcpServerName, env) {
9
+ const client = new MultiServerMCPClient({
10
+ mcpServers: {
11
+ [mcpServerName]: getMCPClientConfig(mcpServerName, env),
12
+ },
13
+ });
14
+ const tools = await client.getTools();
15
+ logger.error(`Loaded ${tools.length} MCP tools: ${tools
16
+ .map((tool) => tool.name)
17
+ .join(', ')}`, {});
18
+ const llm = createLLM(env);
19
+ if (!llm.bindTools) {
20
+ throw new Error('The selected LLM model does not support tool binding');
21
+ }
22
+ const model = llm.bindTools(tools);
23
+ const toolNode = new ToolNode(tools);
24
+ return { model, toolNode };
25
+ }
26
+ export const specializedNode = async (state) => {
27
+ logger.error(`Specialized node executing for agent: ${state.next}`, {});
28
+ const { model, toolNode } = await specializedAgent(state.next, state.mcpEnvironment);
29
+ const promptInfo = getMCPPromptInfo(state.next);
30
+ const systemPrompt = specializedPrompt(promptInfo);
31
+ const systemMessage = new SystemMessage(systemPrompt);
32
+ const response = await model.invoke([systemMessage, ...state.messages]);
33
+ if (response.tool_calls && response.tool_calls.length > 0) {
34
+ logger.error(`Tool calls detected: ${response.tool_calls.map((tc) => tc.name).join(', ')}`, {});
35
+ const toolResults = await toolNode.invoke({
36
+ messages: [...state.messages, response],
37
+ });
38
+ const finalResponse = await model.invoke([
39
+ ...state.messages,
40
+ response,
41
+ ...toolResults.messages,
42
+ ]);
43
+ logger.error('Agent response with tools completed', {
44
+ agent: state.next,
45
+ toolCalls: response.tool_calls,
46
+ toolResults: toolResults,
47
+ toolArgs: response.tool_calls[0].args,
48
+ toolArgsType: typeof response.tool_calls[0].args,
49
+ });
50
+ return {
51
+ messages: [
52
+ new HumanMessage({
53
+ content: finalResponse.content,
54
+ name: state.next,
55
+ }),
56
+ ],
57
+ };
58
+ }
59
+ else {
60
+ logger.error('Agent response without tools', {
61
+ agent: state.next,
62
+ messageLength: response.content.length,
63
+ });
64
+ return {
65
+ messages: [
66
+ new HumanMessage({ content: response.content, name: state.next }),
67
+ ],
68
+ };
69
+ }
70
+ };
71
+ //# sourceMappingURL=specialized.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"specialized.js","sourceRoot":"","sources":["../../../src/graph/agents/specialized.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,66 @@
1
+ import type { BaseMessage } from '@langchain/core/messages';
2
+ import { MCPEnvironment } from './mcps/interfaces.js';
3
+ export declare const GraphAnnotation: import("@langchain/langgraph").AnnotationRoot<{
4
+ messages: import("@langchain/langgraph").BinaryOperatorAggregate<BaseMessage[], BaseMessage[]>;
5
+ next: import("@langchain/langgraph").BinaryOperatorAggregate<string, string>;
6
+ mcpEnvironment: import("@langchain/langgraph").BinaryOperatorAggregate<MCPEnvironment, MCPEnvironment>;
7
+ routingInfo: import("@langchain/langgraph").BinaryOperatorAggregate<{
8
+ reasoning?: string;
9
+ timestamp?: string;
10
+ }, {
11
+ reasoning?: string;
12
+ timestamp?: string;
13
+ }>;
14
+ }>;
15
+ export declare const routingFunction: (state: typeof GraphAnnotation.State) => Promise<"__end__" | "specialized">;
16
+ export declare const graph: import("@langchain/langgraph").CompiledStateGraph<{
17
+ messages: BaseMessage[];
18
+ next: string;
19
+ mcpEnvironment: MCPEnvironment;
20
+ routingInfo: {
21
+ reasoning?: string;
22
+ timestamp?: string;
23
+ };
24
+ }, {
25
+ messages?: BaseMessage[] | undefined;
26
+ next?: string | undefined;
27
+ mcpEnvironment?: MCPEnvironment | undefined;
28
+ routingInfo?: {
29
+ reasoning?: string;
30
+ timestamp?: string;
31
+ } | undefined;
32
+ }, "__start__" | "selector" | "specialized", {
33
+ messages: import("@langchain/langgraph").BinaryOperatorAggregate<BaseMessage[], BaseMessage[]>;
34
+ next: import("@langchain/langgraph").BinaryOperatorAggregate<string, string>;
35
+ mcpEnvironment: import("@langchain/langgraph").BinaryOperatorAggregate<MCPEnvironment, MCPEnvironment>;
36
+ routingInfo: import("@langchain/langgraph").BinaryOperatorAggregate<{
37
+ reasoning?: string;
38
+ timestamp?: string;
39
+ }, {
40
+ reasoning?: string;
41
+ timestamp?: string;
42
+ }>;
43
+ }, {
44
+ messages: import("@langchain/langgraph").BinaryOperatorAggregate<BaseMessage[], BaseMessage[]>;
45
+ next: import("@langchain/langgraph").BinaryOperatorAggregate<string, string>;
46
+ mcpEnvironment: import("@langchain/langgraph").BinaryOperatorAggregate<MCPEnvironment, MCPEnvironment>;
47
+ routingInfo: import("@langchain/langgraph").BinaryOperatorAggregate<{
48
+ reasoning?: string;
49
+ timestamp?: string;
50
+ }, {
51
+ reasoning?: string;
52
+ timestamp?: string;
53
+ }>;
54
+ }, import("@langchain/langgraph").StateDefinition, {
55
+ selector: {
56
+ next: any;
57
+ routingInfo: {
58
+ reasoning: any;
59
+ timestamp: string;
60
+ };
61
+ };
62
+ specialized: {
63
+ messages: import("@langchain/core/messages").HumanMessage[];
64
+ };
65
+ }>;
66
+ //# sourceMappingURL=graph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph.d.ts","sourceRoot":"","sources":["../../src/graph/graph.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAI5D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAItD,eAAO,MAAM,eAAe;;;;;oBAaZ,MAAM;oBACN,MAAM;;oBADN,MAAM;oBACN,MAAM;;EAKpB,CAAC;AAEH,eAAO,MAAM,eAAe,GAAU,OAAO,OAAO,eAAe,CAAC,KAAK,uCAExE,CAAC;AAEF,eAAO,MAAM,KAAK;;;;;oBAZF,MAAM;oBACN,MAAM;;;;;;;oBADN,MAAM;oBACN,MAAM;;;;;;;oBADN,MAAM;oBACN,MAAM;;oBADN,MAAM;oBACN,MAAM;;;;;;;oBADN,MAAM;oBACN,MAAM;;oBADN,MAAM;oBACN,MAAM;;;;;;;;;;;;;EAiByB,CAAC"}
@@ -0,0 +1,31 @@
1
+ import { StateGraph, MemorySaver, Annotation, START, END, messagesStateReducer, } from '@langchain/langgraph';
2
+ import { selectorAgent } from './agents/selector.js';
3
+ import { specializedNode } from './agents/specialized.js';
4
+ export const GraphAnnotation = Annotation.Root({
5
+ messages: Annotation({
6
+ reducer: messagesStateReducer,
7
+ default: () => [],
8
+ }),
9
+ next: Annotation({
10
+ reducer: (x, y) => y ?? x,
11
+ default: () => END,
12
+ }),
13
+ mcpEnvironment: Annotation({
14
+ reducer: (x, y) => y ?? x,
15
+ }),
16
+ routingInfo: Annotation({
17
+ reducer: (x, y) => ({ ...x, ...y }),
18
+ default: () => ({}),
19
+ }),
20
+ });
21
+ export const routingFunction = async (state) => {
22
+ return state.next != END ? 'specialized' : END;
23
+ };
24
+ export const graph = new StateGraph(GraphAnnotation)
25
+ .addNode('selector', selectorAgent)
26
+ .addNode('specialized', specializedNode)
27
+ .addEdge(START, 'selector')
28
+ .addConditionalEdges('selector', routingFunction)
29
+ .addEdge('specialized', END)
30
+ .compile({ checkpointer: new MemorySaver() });
31
+ //# sourceMappingURL=graph.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph.js","sourceRoot":"","sources":["../../src/graph/graph.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,WAAW,EACX,UAAU,EACV,KAAK,EACL,GAAG,EACH,oBAAoB,GACrB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAGrD,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAG1D,MAAM,CAAC,MAAM,eAAe,GAAG,UAAU,CAAC,IAAI,CAAC;IAC7C,QAAQ,EAAE,UAAU,CAAgB;QAClC,OAAO,EAAE,oBAAoB;QAC7B,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE;KAClB,CAAC;IACF,IAAI,EAAE,UAAU,CAAY;QAC1B,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC;QACzB,OAAO,EAAE,GAAG,EAAE,CAAC,GAAgB;KAChC,CAAC;IACF,cAAc,EAAE,UAAU,CAAiB;QACzC,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC;KAC1B,CAAC;IACF,WAAW,EAAE,UAAU,CAGpB;QACD,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;QACnC,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC;KACpB,CAAC;CACH,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,EAAE,KAAmC,EAAE,EAAE;IAC3E,OAAO,KAAK,CAAC,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC;AACjD,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,eAAe,CAAC;KACjD,OAAO,CAAC,UAAU,EAAE,aAAa,CAAC;KAClC,OAAO,CAAC,aAAa,EAAE,eAAe,CAAC;KACvC,OAAO,CAAC,KAAK,EAAE,UAAU,CAAC;KAC1B,mBAAmB,CAAC,UAAU,EAAE,eAAe,CAAC;KAChD,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;KAC3B,OAAO,CAAC,EAAE,YAAY,EAAE,IAAI,WAAW,EAAE,EAAE,CAAC,CAAC"}
@@ -0,0 +1,27 @@
1
+ export interface MCPEnvironment {
2
+ [key: string]: string | undefined;
3
+ }
4
+ export interface MCPClientConfig {
5
+ command: string;
6
+ args: string[];
7
+ transport: 'stdio';
8
+ env?: Record<string, string>;
9
+ encoding?: string;
10
+ stderr?: 'overlapped' | 'pipe' | 'ignore' | 'inherit';
11
+ cwd?: string;
12
+ restart?: {
13
+ enabled?: boolean;
14
+ maxAttempts?: number;
15
+ delayMs?: number;
16
+ };
17
+ }
18
+ export interface MCPPromptInfo {
19
+ expertise: string;
20
+ tools: string[];
21
+ }
22
+ export interface MCPServerInfo {
23
+ client: MCPClientConfig;
24
+ description: string;
25
+ promptInfo: MCPPromptInfo;
26
+ }
27
+ //# sourceMappingURL=interfaces.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../../../src/graph/mcps/interfaces.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CACnC;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;IAEnB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,YAAY,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAC;IACtD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE;QACR,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;CACH;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,eAAe,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,aAAa,CAAC;CAC3B"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=interfaces.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interfaces.js","sourceRoot":"","sources":["../../../src/graph/mcps/interfaces.ts"],"names":[],"mappings":""}
@@ -0,0 +1,15 @@
1
+ import { MCPServerInfo, MCPEnvironment, MCPClientConfig } from './interfaces.js';
2
+ export declare function getMcpInfo(name: string): MCPServerInfo | undefined;
3
+ export declare function getAllMcpInfo(): Record<string, MCPServerInfo>;
4
+ export declare function getMcpNames(): string[];
5
+ export declare const AvailableAgents: string[];
6
+ export type AgentName = (typeof AvailableAgents)[number];
7
+ export declare const getMCPClientConfig: (serverName: string, env?: MCPEnvironment) => MCPClientConfig;
8
+ export declare const getMCPDescription: (serverName: string) => string;
9
+ export declare const getMCPPromptInfo: (serverName: string) => {
10
+ agentName: string;
11
+ expertise: string;
12
+ tools: string[];
13
+ description: string;
14
+ };
15
+ //# sourceMappingURL=utilities.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utilities.d.ts","sourceRoot":"","sources":["../../../src/graph/mcps/utilities.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,aAAa,EACb,cAAc,EACd,eAAe,EAChB,MAAM,iBAAiB,CAAC;AAqBzB,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAGlE;AAED,wBAAgB,aAAa,IAAI,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAE7D;AAED,wBAAgB,WAAW,IAAI,MAAM,EAAE,CAGtC;AAED,eAAO,MAAM,eAAe,UAAgB,CAAC;AAC7C,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAEzD,eAAO,MAAM,kBAAkB,GAC7B,YAAY,MAAM,EAClB,MAAM,cAAc,KACnB,eAgCF,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,YAAY,MAAM,KAAG,MAEtD,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAC3B,YAAY,MAAM,KACjB;IACD,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;CAiBrB,CAAC"}