aiexecode 1.0.90 → 1.0.92
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.
Potentially problematic release.
This version of aiexecode might be problematic. Click here for more details.
- package/README.md +1 -0
- package/index.js +13 -11
- package/mcp-agent-lib/init.sh +3 -0
- package/mcp-agent-lib/package-lock.json +14 -1
- package/mcp-agent-lib/package.json +4 -6
- package/mcp-agent-lib/sampleFastMCPClient/client.py +25 -0
- package/mcp-agent-lib/sampleFastMCPClient/run.sh +3 -0
- package/mcp-agent-lib/sampleFastMCPServer/run.sh +3 -0
- package/mcp-agent-lib/sampleFastMCPServer/server.py +12 -0
- package/mcp-agent-lib/sampleFastMCPServerElicitationRequest/run.sh +3 -0
- package/mcp-agent-lib/sampleFastMCPServerElicitationRequest/server.py +43 -0
- package/mcp-agent-lib/sampleFastMCPServerRootsRequest/server.py +63 -0
- package/mcp-agent-lib/sampleMCPHost/index.js +182 -63
- package/mcp-agent-lib/sampleMCPHost/mcp_config.json +7 -1
- package/mcp-agent-lib/sampleMCPHostFeatures/elicitation.js +151 -0
- package/mcp-agent-lib/sampleMCPHostFeatures/index.js +166 -0
- package/mcp-agent-lib/sampleMCPHostFeatures/roots.js +197 -0
- package/mcp-agent-lib/src/mcp_client.js +129 -67
- package/mcp-agent-lib/src/mcp_message_logger.js +516 -0
- package/package.json +3 -1
- package/payload_viewer/out/404/index.html +1 -1
- package/payload_viewer/out/404.html +1 -1
- package/payload_viewer/out/index.html +1 -1
- package/payload_viewer/out/index.txt +1 -1
- package/src/LLMClient/client.js +992 -0
- package/src/LLMClient/converters/input-normalizer.js +238 -0
- package/src/LLMClient/converters/responses-to-claude.js +454 -0
- package/src/LLMClient/converters/responses-to-gemini.js +648 -0
- package/src/LLMClient/converters/responses-to-ollama.js +348 -0
- package/src/LLMClient/errors.js +372 -0
- package/src/LLMClient/index.js +31 -0
- package/src/commands/apikey.js +10 -22
- package/src/commands/model.js +28 -28
- package/src/commands/reasoning_effort.js +9 -23
- package/src/config/ai_models.js +212 -0
- package/src/config/feature_flags.js +1 -1
- package/src/frontend/App.js +5 -10
- package/src/frontend/components/CurrentModelView.js +0 -33
- package/src/frontend/components/Footer.js +3 -3
- package/src/frontend/components/ModelListView.js +30 -87
- package/src/frontend/components/ModelUpdatedView.js +7 -142
- package/src/frontend/components/SetupWizard.js +37 -32
- package/src/system/ai_request.js +57 -42
- package/src/util/config.js +26 -4
- package/src/util/setup_wizard.js +1 -6
- package/mcp-agent-lib/.claude/settings.local.json +0 -9
- package/src/config/openai_models.js +0 -152
- /package/payload_viewer/out/_next/static/{w4dMVYalgk7djrLxRxWiE → d0-fu2rgYnshgGFPxr1CR}/_buildManifest.js +0 -0
- /package/payload_viewer/out/_next/static/{w4dMVYalgk7djrLxRxWiE → d0-fu2rgYnshgGFPxr1CR}/_clientMiddlewareManifest.json +0 -0
- /package/payload_viewer/out/_next/static/{w4dMVYalgk7djrLxRxWiE → d0-fu2rgYnshgGFPxr1CR}/_ssgManifest.js +0 -0
package/README.md
CHANGED
package/index.js
CHANGED
|
@@ -282,24 +282,26 @@ if (dependencyCheck.warnings && dependencyCheck.warnings.length > 0) {
|
|
|
282
282
|
}
|
|
283
283
|
|
|
284
284
|
// 환경변수 설정
|
|
285
|
-
if (!process.env.
|
|
286
|
-
process.env.
|
|
285
|
+
if (!process.env.API_KEY && settings?.API_KEY) {
|
|
286
|
+
process.env.API_KEY = settings.API_KEY;
|
|
287
287
|
}
|
|
288
|
-
if (!process.env.
|
|
289
|
-
process.env.
|
|
288
|
+
if (!process.env.MODEL && settings?.MODEL) {
|
|
289
|
+
process.env.MODEL = settings.MODEL;
|
|
290
290
|
}
|
|
291
|
-
if (!process.env.
|
|
292
|
-
process.env.
|
|
291
|
+
if (!process.env.REASONING_EFFORT && settings?.REASONING_EFFORT) {
|
|
292
|
+
process.env.REASONING_EFFORT = settings.REASONING_EFFORT;
|
|
293
293
|
}
|
|
294
294
|
|
|
295
295
|
// 최종 검증
|
|
296
|
-
if (!process.env.
|
|
297
|
-
console.log(chalk.red('\nStartup Failed: Missing
|
|
296
|
+
if (!process.env.API_KEY) {
|
|
297
|
+
console.log(chalk.red('\nStartup Failed: Missing API Key\n'));
|
|
298
298
|
console.log(chalk.yellow('Reason:'));
|
|
299
|
-
console.log('
|
|
299
|
+
console.log(' API_KEY is not configured in the settings.');
|
|
300
300
|
console.log(chalk.yellow('\nSolution:'));
|
|
301
|
-
console.log(' 1. Obtain an API key from OpenAI:');
|
|
302
|
-
console.log(chalk.cyan(' https://platform.openai.com/account/api-keys'));
|
|
301
|
+
console.log(' 1. Obtain an API key from your provider (OpenAI, Google, Anthropic):');
|
|
302
|
+
console.log(chalk.cyan(' OpenAI: https://platform.openai.com/account/api-keys'));
|
|
303
|
+
console.log(chalk.cyan(' Google: https://makersuite.google.com/app/apikey'));
|
|
304
|
+
console.log(chalk.cyan(' Anthropic: https://console.anthropic.com/settings/keys'));
|
|
303
305
|
console.log(` 2. Add the API key to your settings file:`);
|
|
304
306
|
console.log(chalk.cyan(` ${SETTINGS_FILE}`));
|
|
305
307
|
console.log(' 3. Or run the setup wizard again by deleting the settings file');
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
cd sampleFastMCPClient && python3 -m venv venv && venv/bin/pip install fastmcp && cd .. && echo "sampleFastMCPClient done"
|
|
2
|
+
cd sampleFastMCPServer && python3 -m venv venv && venv/bin/pip install fastmcp && cd .. && echo "sampleFastMCPServer done"
|
|
3
|
+
cd sampleFastMCPServerElicitationRequest && python3 -m venv venv && venv/bin/pip install fastmcp && cd .. && echo "sampleFastMCPServerElicitationRequest done"
|
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@modelcontextprotocol/sdk": "^1.18.1",
|
|
13
|
-
"axios": "^1.6.0"
|
|
13
|
+
"axios": "^1.6.0",
|
|
14
|
+
"chalk": "^5.6.2"
|
|
14
15
|
},
|
|
15
16
|
"devDependencies": {},
|
|
16
17
|
"engines": {
|
|
@@ -144,6 +145,18 @@
|
|
|
144
145
|
"url": "https://github.com/sponsors/ljharb"
|
|
145
146
|
}
|
|
146
147
|
},
|
|
148
|
+
"node_modules/chalk": {
|
|
149
|
+
"version": "5.6.2",
|
|
150
|
+
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz",
|
|
151
|
+
"integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==",
|
|
152
|
+
"license": "MIT",
|
|
153
|
+
"engines": {
|
|
154
|
+
"node": "^12.17.0 || ^14.13 || >=16.0.0"
|
|
155
|
+
},
|
|
156
|
+
"funding": {
|
|
157
|
+
"url": "https://github.com/chalk/chalk?sponsor=1"
|
|
158
|
+
}
|
|
159
|
+
},
|
|
147
160
|
"node_modules/combined-stream": {
|
|
148
161
|
"version": "1.0.8",
|
|
149
162
|
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
from fastmcp import Client
|
|
3
|
+
|
|
4
|
+
client = Client("../sampleFastMCPServer/server.py")
|
|
5
|
+
|
|
6
|
+
async def main():
|
|
7
|
+
print("")
|
|
8
|
+
async with client:
|
|
9
|
+
print(f"접속상태: {client.is_connected()}")
|
|
10
|
+
print("")
|
|
11
|
+
|
|
12
|
+
tools = await client.list_tools()
|
|
13
|
+
print(f"사용가능한 도구들: {tools}")
|
|
14
|
+
print("")
|
|
15
|
+
|
|
16
|
+
if any(tool.name == "add" for tool in tools):
|
|
17
|
+
result = await client.call_tool("add", {"a": 3, "b": 7})
|
|
18
|
+
print(f"add 도구 사용의 결과: {result}")
|
|
19
|
+
print("")
|
|
20
|
+
|
|
21
|
+
print(f"접속상태: {client.is_connected()}")
|
|
22
|
+
print("")
|
|
23
|
+
|
|
24
|
+
if __name__ == "__main__":
|
|
25
|
+
asyncio.run(main())
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
from fastmcp import FastMCP
|
|
2
|
+
from fastmcp.server import Context
|
|
3
|
+
|
|
4
|
+
mcp = FastMCP("Elicitation Example Server")
|
|
5
|
+
|
|
6
|
+
@mcp.tool
|
|
7
|
+
async def add_with_confirmation(a: int, b: int, ctx: Context) -> str:
|
|
8
|
+
"""두 숫자를 더합니다. 실행 전에 사용자 확인을 요청합니다."""
|
|
9
|
+
|
|
10
|
+
# Elicitation 요청 - 사용자에게 확인 요청 (boolean 타입 사용)
|
|
11
|
+
result = await ctx.elicit(
|
|
12
|
+
message=f"{a} + {b}를 계산하시겠습니까?",
|
|
13
|
+
response_type=bool
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
# 사용자 응답 확인
|
|
17
|
+
if hasattr(result, 'data') and result.data:
|
|
18
|
+
calculation_result = a + b
|
|
19
|
+
response = f"계산 완료: {a} + {b} = {calculation_result}"
|
|
20
|
+
return response
|
|
21
|
+
else:
|
|
22
|
+
return f"계산이 취소되었습니다. (action: {type(result).__name__})"
|
|
23
|
+
|
|
24
|
+
@mcp.tool
|
|
25
|
+
async def greet_user(ctx: Context) -> str:
|
|
26
|
+
"""사용자의 이름을 물어보고 인사합니다."""
|
|
27
|
+
|
|
28
|
+
# Elicitation 요청 - 사용자 이름 입력 받기
|
|
29
|
+
result = await ctx.elicit(
|
|
30
|
+
message="안녕하세요! 당신의 이름을 알려주세요.",
|
|
31
|
+
response_type=str
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
if hasattr(result, 'data'):
|
|
35
|
+
name = result.data
|
|
36
|
+
greeting = f"안녕하세요, {name}님!"
|
|
37
|
+
return greeting
|
|
38
|
+
else:
|
|
39
|
+
return f"인사를 건너뛰었습니다. (action: {type(result).__name__})"
|
|
40
|
+
|
|
41
|
+
mcp.run()
|
|
42
|
+
|
|
43
|
+
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
from fastmcp import FastMCP
|
|
2
|
+
from fastmcp.server import Context
|
|
3
|
+
import os
|
|
4
|
+
|
|
5
|
+
mcp = FastMCP("Roots Example Server")
|
|
6
|
+
|
|
7
|
+
@mcp.tool
|
|
8
|
+
async def list_accessible_roots(ctx: Context) -> str:
|
|
9
|
+
"""클라이언트가 제공한 roots를 조회합니다."""
|
|
10
|
+
|
|
11
|
+
# Roots 목록 요청
|
|
12
|
+
roots = await ctx.list_roots()
|
|
13
|
+
|
|
14
|
+
if not roots:
|
|
15
|
+
return "클라이언트가 제공한 roots가 없습니다."
|
|
16
|
+
|
|
17
|
+
result = "클라이언트 Roots:\n"
|
|
18
|
+
for idx, root in enumerate(roots, 1):
|
|
19
|
+
result += f"{idx}. {root.name or '(이름 없음)'}: {root.uri}\n"
|
|
20
|
+
|
|
21
|
+
return result
|
|
22
|
+
|
|
23
|
+
@mcp.tool
|
|
24
|
+
async def count_files_in_root(root_index: int, ctx: Context) -> str:
|
|
25
|
+
"""지정된 root의 파일 개수를 계산합니다."""
|
|
26
|
+
|
|
27
|
+
# Roots 목록 요청
|
|
28
|
+
roots = await ctx.list_roots()
|
|
29
|
+
|
|
30
|
+
if not roots:
|
|
31
|
+
return "클라이언트가 제공한 roots가 없습니다."
|
|
32
|
+
|
|
33
|
+
if root_index < 1 or root_index > len(roots):
|
|
34
|
+
return f"잘못된 인덱스입니다. 1부터 {len(roots)} 사이의 값을 입력하세요."
|
|
35
|
+
|
|
36
|
+
selected_root = roots[root_index - 1]
|
|
37
|
+
uri = str(selected_root.uri) # FileUrl 객체를 문자열로 변환
|
|
38
|
+
|
|
39
|
+
# file:// 제거하고 실제 경로 추출
|
|
40
|
+
if uri.startswith("file://"):
|
|
41
|
+
path = uri[7:] # "file://" 제거
|
|
42
|
+
else:
|
|
43
|
+
return f"지원하지 않는 URI 스키마입니다: {uri}"
|
|
44
|
+
|
|
45
|
+
try:
|
|
46
|
+
# 파일/디렉토리 확인
|
|
47
|
+
if not os.path.exists(path):
|
|
48
|
+
return f"경로가 존재하지 않습니다: {path}"
|
|
49
|
+
|
|
50
|
+
if os.path.isfile(path):
|
|
51
|
+
return f"단일 파일입니다: {selected_root.name or path}"
|
|
52
|
+
|
|
53
|
+
# 디렉토리의 파일 개수 계산
|
|
54
|
+
file_count = 0
|
|
55
|
+
for root, dirs, files in os.walk(path):
|
|
56
|
+
file_count += len(files)
|
|
57
|
+
|
|
58
|
+
return f"Root '{selected_root.name or path}'에 총 {file_count}개의 파일이 있습니다."
|
|
59
|
+
|
|
60
|
+
except Exception as e:
|
|
61
|
+
return f"오류 발생: {str(e)}"
|
|
62
|
+
|
|
63
|
+
mcp.run()
|
|
@@ -45,12 +45,38 @@ import { MCPAgentClient } from '../index.js';
|
|
|
45
45
|
import { readFileSync } from 'fs';
|
|
46
46
|
import { join, dirname } from 'path';
|
|
47
47
|
import { fileURLToPath } from 'url';
|
|
48
|
+
import * as readline from 'readline';
|
|
49
|
+
import chalk from 'chalk';
|
|
48
50
|
|
|
49
51
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
50
52
|
|
|
53
|
+
// 색상 팔레트 정의
|
|
54
|
+
const colors = {
|
|
55
|
+
cyan: chalk.rgb(198, 219, 218), // #C6DBDA - 연한 청록색
|
|
56
|
+
pink: chalk.rgb(254, 225, 232), // #FEE1E8 - 연한 분홍색
|
|
57
|
+
peach: chalk.rgb(254, 215, 195), // #FED7C3 - 연한 복숭아색
|
|
58
|
+
yellow: chalk.rgb(246, 234, 194), // #F6EAC2 - 연한 노란색
|
|
59
|
+
purple: chalk.rgb(236, 213, 227), // #ECD5E3 - 연한 보라색
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
// Enter 키 입력을 기다리는 함수
|
|
63
|
+
async function waitForEnter(message = '\n계속하려면 Enter 키를 누르세요...') {
|
|
64
|
+
const rl = readline.createInterface({
|
|
65
|
+
input: process.stdin,
|
|
66
|
+
output: process.stdout
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
return new Promise((resolve) => {
|
|
70
|
+
rl.question(message, () => {
|
|
71
|
+
rl.close();
|
|
72
|
+
resolve();
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
51
77
|
async function main() {
|
|
52
78
|
console.log('='.repeat(50));
|
|
53
|
-
console.log('MCP 사용 예시 - 시작합니다...');
|
|
79
|
+
console.log(colors.peach.bold('MCP 사용 예시 - 시작합니다...'));
|
|
54
80
|
console.log('='.repeat(50));
|
|
55
81
|
|
|
56
82
|
// ========================================
|
|
@@ -58,15 +84,16 @@ async function main() {
|
|
|
58
84
|
// ========================================
|
|
59
85
|
// mcp_config.json 파일에는 어떤 MCP 서버들을 사용할지 정의되어 있습니다.
|
|
60
86
|
// 예: context7(문서 검색), chrome-devtools(브라우저 제어) 등
|
|
61
|
-
console.log('\n[1단계] MCP 서버 설정을 불러옵니다...');
|
|
62
|
-
console.log(' 설명: mcp_config.json 파일에서 연결할 서버 목록을 읽어옵니다');
|
|
87
|
+
console.log(colors.cyan.bold('\n[1단계] MCP 서버 설정을 불러옵니다...'));
|
|
88
|
+
console.log(colors.cyan(' 설명: mcp_config.json 파일에서 연결할 서버 목록을 읽어옵니다'));
|
|
89
|
+
await waitForEnter();
|
|
63
90
|
|
|
64
91
|
const configPath = join(__dirname, 'mcp_config.json');
|
|
65
92
|
const config = JSON.parse(readFileSync(configPath, 'utf-8'));
|
|
66
93
|
|
|
67
|
-
console.log(` ✓ ${Object.keys(config.mcpServers).length}개의 서버 설정을 불러왔습니다`);
|
|
94
|
+
console.log(colors.cyan.bold(` ✓ ${Object.keys(config.mcpServers).length}개의 서버 설정을 불러왔습니다`));
|
|
68
95
|
Object.keys(config.mcpServers).forEach(name => {
|
|
69
|
-
console.log(` - ${name}`);
|
|
96
|
+
console.log(colors.cyan(` - ${name}`));
|
|
70
97
|
});
|
|
71
98
|
|
|
72
99
|
// ========================================
|
|
@@ -74,92 +101,111 @@ async function main() {
|
|
|
74
101
|
// ========================================
|
|
75
102
|
// MCP Agent는 여러 MCP 서버들과 통신하는 관리자입니다.
|
|
76
103
|
// 이 객체를 통해 서버에 연결하고, 도구를 실행할 수 있습니다.
|
|
77
|
-
console.log('\n[2단계] MCP Agent를 만듭니다...');
|
|
78
|
-
console.log(' 설명: MCP 서버들을 관리할 Agent 객체를 생성합니다');
|
|
104
|
+
console.log(colors.pink.bold('\n[2단계] MCP Agent를 만듭니다...'));
|
|
105
|
+
console.log(colors.pink(' 설명: MCP 서버들을 관리할 Agent 객체를 생성합니다'));
|
|
106
|
+
await waitForEnter();
|
|
79
107
|
|
|
80
108
|
const mcpAgent = new MCPAgentClient({
|
|
81
109
|
logLevel: 'info', // 로그 레벨 설정
|
|
82
|
-
enableConsoleDebug: true
|
|
110
|
+
enableConsoleDebug: true, // 디버그 메시지 콘솔 출력
|
|
111
|
+
enableRawMessageLogging: true, // RAW 메시지 로깅 활성화
|
|
112
|
+
messageLoggerOptions: {
|
|
113
|
+
logDir: join(__dirname, 'log'), // 로그 디렉토리 경로
|
|
114
|
+
output: 'file', // 파일로만 출력
|
|
115
|
+
prettyPrint: true // JSON 예쁘게 출력
|
|
116
|
+
},
|
|
117
|
+
clientInfo: {
|
|
118
|
+
name: 'ASAN-AI-Agent', // 클라이언트 이름
|
|
119
|
+
version: '1.0.0' // 클라이언트 버전
|
|
120
|
+
}
|
|
83
121
|
});
|
|
84
|
-
console.log(' ✓ MCP Agent가 만들어졌습니다');
|
|
122
|
+
console.log(colors.pink.bold(' ✓ MCP Agent가 만들어졌습니다'));
|
|
85
123
|
|
|
86
124
|
// ========================================
|
|
87
125
|
// [3단계] MCP 서버에 연결
|
|
88
126
|
// ========================================
|
|
89
127
|
// initialize()를 호출하면 설정 파일에 있는 모든 서버에 연결을 시도합니다.
|
|
90
128
|
// HTTP, stdio 등 다양한 방식으로 서버와 통신할 수 있습니다.
|
|
91
|
-
console.log('\n[3단계] MCP Agent를 초기화하고 서버들에 연결합니다...');
|
|
92
|
-
console.log(' 설명: 설정된 모든 MCP 서버에 실제로 연결합니다');
|
|
129
|
+
console.log(colors.peach.bold('\n[3단계] MCP Agent를 초기화하고 서버들에 연결합니다...'));
|
|
130
|
+
console.log(colors.peach(' 설명: 설정된 모든 MCP 서버에 실제로 연결합니다'));
|
|
131
|
+
await waitForEnter();
|
|
93
132
|
|
|
94
133
|
await mcpAgent.initialize(config);
|
|
95
|
-
console.log(' ✓ 모든 서버에 연결되었습니다');
|
|
134
|
+
console.log(colors.peach.bold(' ✓ 모든 서버에 연결되었습니다'));
|
|
96
135
|
|
|
97
136
|
// ========================================
|
|
98
137
|
// [4단계] 사용 가능한 도구 목록 조회
|
|
99
138
|
// ========================================
|
|
100
139
|
// 연결된 모든 MCP 서버들이 제공하는 도구(tool)들을 가져옵니다.
|
|
101
140
|
// 각 도구는 이름, 설명, 입력 파라미터 정보를 가지고 있습니다.
|
|
102
|
-
console.log('\n[4단계] 사용 가능한 도구 목록을 가져옵니다...');
|
|
103
|
-
console.log(' 설명: 연결된 서버들이 제공하는 모든 도구의 목록과 스펙을 확인합니다');
|
|
141
|
+
console.log(colors.yellow.bold('\n[4단계] 사용 가능한 도구 목록을 가져옵니다...'));
|
|
142
|
+
console.log(colors.yellow(' 설명: 연결된 서버들이 제공하는 모든 도구의 목록과 스펙을 확인합니다'));
|
|
143
|
+
await waitForEnter();
|
|
104
144
|
|
|
105
145
|
const availableTools = mcpAgent.getAvailableTools();
|
|
106
|
-
console.log(` ✓ ${availableTools.length}개의 도구를 찾았습니다`);
|
|
146
|
+
console.log(colors.yellow.bold(` ✓ ${availableTools.length}개의 도구를 찾았습니다`));
|
|
107
147
|
|
|
108
148
|
// 각 도구의 상세 정보 출력
|
|
109
|
-
console.log('\n 각 도구의 상세 정보:');
|
|
149
|
+
console.log(colors.yellow.bold('\n 각 도구의 상세 정보:'));
|
|
110
150
|
availableTools.forEach((tool, index) => {
|
|
111
|
-
console.log(`\n [${index + 1}] ${tool.name}`);
|
|
112
|
-
console.log(` 서버: ${tool.server}`);
|
|
113
|
-
console.log(` 설명: ${tool.description || '설명 없음'}`);
|
|
151
|
+
console.log(colors.yellow.bold(`\n [${index + 1}] ${tool.name}`));
|
|
152
|
+
console.log(colors.yellow.italic(` 서버: ${tool.server}`));
|
|
153
|
+
console.log(colors.yellow(` 설명: ${tool.description || '설명 없음'}`));
|
|
114
154
|
|
|
115
155
|
if (tool.inputSchema && tool.inputSchema.properties) {
|
|
116
156
|
const props = tool.inputSchema.properties;
|
|
117
157
|
const required = tool.inputSchema.required || [];
|
|
118
158
|
|
|
119
|
-
console.log(` 입력값:`);
|
|
159
|
+
console.log(colors.yellow.bold(` 입력값:`));
|
|
120
160
|
Object.entries(props).forEach(([propName, propSchema]) => {
|
|
121
161
|
const isRequired = required.includes(propName) ? '(필수)' : '(선택)';
|
|
122
162
|
const type = propSchema.type || '타입 미지정';
|
|
123
163
|
const desc = propSchema.description || '설명 없음';
|
|
124
164
|
|
|
125
|
-
console.log(` - ${propName}
|
|
126
|
-
console.log(` 타입:
|
|
127
|
-
console.log(` 설명:
|
|
165
|
+
console.log(colors.yellow(` - ${propName} `) + (isRequired === '(필수)' ? colors.peach.bold(isRequired) : colors.cyan(isRequired)));
|
|
166
|
+
console.log(colors.yellow(` 타입: `) + colors.pink(type));
|
|
167
|
+
console.log(colors.yellow(` 설명: `) + colors.purple.italic(desc));
|
|
128
168
|
|
|
129
169
|
// 추가 스키마 정보 출력
|
|
130
170
|
if (propSchema.items) {
|
|
131
|
-
console.log(` 배열 항목 타입:
|
|
171
|
+
console.log(colors.yellow(` 배열 항목 타입: `) + colors.cyan(JSON.stringify(propSchema.items)));
|
|
132
172
|
}
|
|
133
173
|
});
|
|
134
174
|
|
|
135
175
|
// 전체 스키마 출력 (디버깅용)
|
|
136
|
-
|
|
176
|
+
if (false) {
|
|
177
|
+
console.log(` 전체 스키마: ${JSON.stringify(tool.inputSchema, null, 2)}`);
|
|
178
|
+
}
|
|
137
179
|
} else {
|
|
138
|
-
console.log(` 입력값: 없음`);
|
|
180
|
+
console.log(colors.yellow.italic(` 입력값: 없음`));
|
|
139
181
|
}
|
|
140
182
|
});
|
|
141
183
|
|
|
142
184
|
// ========================================
|
|
143
|
-
// [5단계] 도구 실행 예시
|
|
185
|
+
// [5단계] 도구 실행 예시
|
|
144
186
|
// ========================================
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
187
|
+
console.log(colors.purple.bold('\n[5단계] 도구 실행 예시...'));
|
|
188
|
+
console.log(colors.purple(' 설명: 연결된 서버들의 도구를 실제로 사용해봅니다'));
|
|
189
|
+
await waitForEnter();
|
|
190
|
+
|
|
191
|
+
// ========================================
|
|
192
|
+
// [5-1] Chrome DevTools - 브라우저 제어
|
|
193
|
+
// ========================================
|
|
194
|
+
console.log(colors.purple.bold('\n [5-1] Chrome DevTools 서버의 도구 사용'));
|
|
195
|
+
console.log(colors.purple(' 설명: 브라우저를 열고 JavaScript를 실행합니다'));
|
|
196
|
+
await waitForEnter();
|
|
151
197
|
|
|
152
198
|
// new_page 도구 찾기
|
|
153
199
|
const newPageTool = availableTools.find(tool => tool.name === 'new_page');
|
|
154
200
|
|
|
155
201
|
if (newPageTool) {
|
|
156
|
-
console.log(`\n
|
|
157
|
-
console.log(` 실행할 도구: ${newPageTool.name}`);
|
|
158
|
-
console.log(` 서버: ${newPageTool.server}`);
|
|
202
|
+
console.log(colors.purple.bold(`\n 새 페이지 열기`));
|
|
203
|
+
console.log(colors.purple.italic(` 실행할 도구: ${newPageTool.name}`));
|
|
204
|
+
console.log(colors.purple.italic(` 서버: ${newPageTool.server}`));
|
|
159
205
|
|
|
160
206
|
try {
|
|
161
207
|
// about:blank 페이지 열기
|
|
162
|
-
console.log(' about:blank 페이지를 엽니다...');
|
|
208
|
+
console.log(colors.purple(' about:blank 페이지를 엽니다...'));
|
|
163
209
|
|
|
164
210
|
// mcpAgent.executeTool() 함수 설명:
|
|
165
211
|
// - AI가 "new_page 도구를 url: 'about:blank'로 실행해줘"라고 요청하면
|
|
@@ -170,20 +216,20 @@ async function main() {
|
|
|
170
216
|
const result = await mcpAgent.executeTool('new_page', { url: 'about:blank' });
|
|
171
217
|
|
|
172
218
|
if (result.success) {
|
|
173
|
-
console.log(' ✓ 페이지가 열렸습니다');
|
|
174
|
-
console.log(' 결과:'
|
|
219
|
+
console.log(colors.purple.bold(' ✓ 페이지가 열렸습니다'));
|
|
220
|
+
console.log(colors.purple(' 결과: ') + colors.peach(JSON.stringify(result.data, null, 2)));
|
|
175
221
|
|
|
176
222
|
// ========================================
|
|
177
|
-
//
|
|
223
|
+
// JavaScript 실행으로 카운트다운 표시
|
|
178
224
|
// ========================================
|
|
179
225
|
// evaluate_script 도구를 사용하여 페이지에서 JavaScript를 실행합니다.
|
|
180
226
|
// 10부터 0까지 숫자를 화면 중앙에 크게 표시합니다.
|
|
181
|
-
console.log('\n
|
|
182
|
-
console.log(' 설명: evaluate_script 도구로 페이지 내용을 동적으로 변경합니다');
|
|
183
|
-
console.log(' 페이지에 10부터 0까지 카운트다운을 표시합니다...');
|
|
227
|
+
console.log(colors.purple.bold('\n 페이지에 카운트다운 표시하기'));
|
|
228
|
+
console.log(colors.purple(' 설명: evaluate_script 도구로 페이지 내용을 동적으로 변경합니다'));
|
|
229
|
+
console.log(colors.purple(' 페이지에 10부터 0까지 카운트다운을 표시합니다...'));
|
|
184
230
|
|
|
185
231
|
for (let count = 10; count >= 0; count--) {
|
|
186
|
-
console.log(`\n 현재 카운트:
|
|
232
|
+
console.log(colors.purple.bold(`\n 현재 카운트: `) + colors.peach.bold(count));
|
|
187
233
|
|
|
188
234
|
// JavaScript 실행으로 body에 숫자 표시
|
|
189
235
|
//
|
|
@@ -212,9 +258,9 @@ async function main() {
|
|
|
212
258
|
});
|
|
213
259
|
|
|
214
260
|
if (scriptResult.success) {
|
|
215
|
-
console.log(` ✓ ${count} 표시 완료`);
|
|
261
|
+
console.log(colors.purple.bold(` ✓ ${count} 표시 완료`));
|
|
216
262
|
} else {
|
|
217
|
-
console.log(` ✗ 스크립트 실행 실패:
|
|
263
|
+
console.log(colors.pink.bold(` ✗ 스크립트 실행 실패: `) + colors.pink(scriptResult.error));
|
|
218
264
|
}
|
|
219
265
|
|
|
220
266
|
// 0.1초 대기 (마지막 카운트에서는 대기하지 않음)
|
|
@@ -223,16 +269,86 @@ async function main() {
|
|
|
223
269
|
}
|
|
224
270
|
}
|
|
225
271
|
|
|
226
|
-
console.log('\n ✓ 카운트다운 완료');
|
|
272
|
+
console.log(colors.purple.bold('\n ✓ 카운트다운 완료'));
|
|
273
|
+
} else {
|
|
274
|
+
console.log(colors.pink.bold(` ✗ 실행 실패: `) + colors.pink(result.error));
|
|
275
|
+
}
|
|
276
|
+
} catch (error) {
|
|
277
|
+
console.log(colors.pink.bold(` ✗ 오류: `) + colors.pink(error.message));
|
|
278
|
+
}
|
|
279
|
+
} else {
|
|
280
|
+
console.log(colors.purple.italic(' new_page 도구를 찾을 수 없습니다'));
|
|
281
|
+
console.log(colors.purple(' 사용 가능한 도구: ') + colors.yellow(availableTools.map(t => t.name).join(', ')));
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// ========================================
|
|
285
|
+
// [5-2] Context7 - 라이브러리 문서 검색
|
|
286
|
+
// ========================================
|
|
287
|
+
console.log(colors.purple.bold('\n [5-2] Context7 서버의 도구 사용'));
|
|
288
|
+
console.log(colors.purple(' 설명: 라이브러리 ID를 검색합니다'));
|
|
289
|
+
await waitForEnter();
|
|
290
|
+
|
|
291
|
+
const resolveLibraryTool = availableTools.find(tool => tool.name === 'resolve-library-id');
|
|
292
|
+
|
|
293
|
+
if (resolveLibraryTool) {
|
|
294
|
+
console.log(colors.purple.bold(`\n 라이브러리 검색`));
|
|
295
|
+
console.log(colors.purple.italic(` 실행할 도구: ${resolveLibraryTool.name}`));
|
|
296
|
+
console.log(colors.purple.italic(` 서버: ${resolveLibraryTool.server}`));
|
|
297
|
+
|
|
298
|
+
try {
|
|
299
|
+
console.log(colors.purple(' "react" 라이브러리를 검색합니다...'));
|
|
300
|
+
|
|
301
|
+
const resolveResult = await mcpAgent.executeTool('resolve-library-id', {
|
|
302
|
+
libraryName: 'react'
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
if (resolveResult.success) {
|
|
306
|
+
console.log(colors.purple.bold(' ✓ 라이브러리 검색 완료'));
|
|
307
|
+
console.log(colors.purple(' 결과:'));
|
|
308
|
+
console.log(colors.peach(JSON.stringify(resolveResult.data, null, 2)));
|
|
309
|
+
} else {
|
|
310
|
+
console.log(colors.pink.bold(` ✗ 검색 실패: `) + colors.pink(resolveResult.error));
|
|
311
|
+
}
|
|
312
|
+
} catch (error) {
|
|
313
|
+
console.log(colors.pink.bold(` ✗ 오류: `) + colors.pink(error.message));
|
|
314
|
+
}
|
|
315
|
+
} else {
|
|
316
|
+
console.log(colors.purple.italic(' resolve-library-id 도구를 찾을 수 없습니다'));
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// ========================================
|
|
320
|
+
// [5-3] Simple Calculator - 덧셈 계산
|
|
321
|
+
// ========================================
|
|
322
|
+
console.log(colors.purple.bold('\n [5-3] Simple Calculator 서버의 도구 사용'));
|
|
323
|
+
console.log(colors.purple(' 설명: 두 숫자를 더합니다'));
|
|
324
|
+
await waitForEnter();
|
|
325
|
+
|
|
326
|
+
const addTool = availableTools.find(tool => tool.name === 'add');
|
|
327
|
+
|
|
328
|
+
if (addTool) {
|
|
329
|
+
console.log(colors.purple.bold(`\n 덧셈 계산`));
|
|
330
|
+
console.log(colors.purple.italic(` 실행할 도구: ${addTool.name}`));
|
|
331
|
+
console.log(colors.purple.italic(` 서버: ${addTool.server}`));
|
|
332
|
+
|
|
333
|
+
try {
|
|
334
|
+
console.log(colors.purple(' 5 + 3을 계산합니다...'));
|
|
335
|
+
|
|
336
|
+
const addResult = await mcpAgent.executeTool('add', {
|
|
337
|
+
a: 5,
|
|
338
|
+
b: 3
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
if (addResult.success) {
|
|
342
|
+
console.log(colors.purple.bold(' ✓ 계산 완료'));
|
|
343
|
+
console.log(colors.purple(' 결과: ') + colors.peach.bold(`5 + 3 = ${JSON.stringify(addResult.data)}`));
|
|
227
344
|
} else {
|
|
228
|
-
console.log(` ✗
|
|
345
|
+
console.log(colors.pink.bold(` ✗ 계산 실패: `) + colors.pink(addResult.error));
|
|
229
346
|
}
|
|
230
347
|
} catch (error) {
|
|
231
|
-
console.log(` ✗ 오류:
|
|
348
|
+
console.log(colors.pink.bold(` ✗ 오류: `) + colors.pink(error.message));
|
|
232
349
|
}
|
|
233
350
|
} else {
|
|
234
|
-
console.log('
|
|
235
|
-
console.log(' 사용 가능한 도구:', availableTools.map(t => t.name).join(', '));
|
|
351
|
+
console.log(colors.purple.italic(' add 도구를 찾을 수 없습니다'));
|
|
236
352
|
}
|
|
237
353
|
|
|
238
354
|
// ========================================
|
|
@@ -240,28 +356,31 @@ async function main() {
|
|
|
240
356
|
// ========================================
|
|
241
357
|
// 프로그램을 종료하기 전에 모든 MCP 서버와의 연결을 정리합니다.
|
|
242
358
|
// cleanup()을 호출하면 열려있던 모든 연결이 안전하게 닫힙니다.
|
|
243
|
-
console.log('\n[6단계] 연결을 정리합니다...');
|
|
244
|
-
console.log(' 설명: 모든 MCP 서버와의 연결을 종료하고 리소스를 정리합니다');
|
|
359
|
+
console.log(colors.cyan.bold('\n[6단계] 연결을 정리합니다...'));
|
|
360
|
+
console.log(colors.cyan(' 설명: 모든 MCP 서버와의 연결을 종료하고 리소스를 정리합니다'));
|
|
361
|
+
await waitForEnter();
|
|
245
362
|
|
|
246
363
|
await mcpAgent.cleanup();
|
|
247
|
-
console.log(' ✓ 모든 연결이 종료되었습니다');
|
|
364
|
+
console.log(colors.cyan.bold(' ✓ 모든 연결이 종료되었습니다'));
|
|
248
365
|
|
|
249
366
|
console.log('\n' + '='.repeat(50));
|
|
250
|
-
console.log('MCP 사용 예시 - 완료!');
|
|
367
|
+
console.log(colors.peach.bold('MCP 사용 예시 - 완료!'));
|
|
251
368
|
console.log('='.repeat(50));
|
|
252
|
-
console.log('\n요약:');
|
|
253
|
-
console.log(' 1. 설정 파일에서 MCP 서버 목록을 읽었습니다');
|
|
254
|
-
console.log(' 2. MCP Agent 객체를 생성하고 서버에 연결했습니다');
|
|
255
|
-
console.log(' 3. 연결된 서버들이 제공하는 도구 목록을 확인했습니다');
|
|
256
|
-
console.log(' 4.
|
|
257
|
-
console.log(' 5.
|
|
369
|
+
console.log(colors.yellow.bold('\n요약:'));
|
|
370
|
+
console.log(colors.cyan(' 1. 설정 파일에서 MCP 서버 목록을 읽었습니다'));
|
|
371
|
+
console.log(colors.pink(' 2. MCP Agent 객체를 생성하고 서버에 연결했습니다'));
|
|
372
|
+
console.log(colors.peach(' 3. 연결된 서버들이 제공하는 도구 목록을 확인했습니다'));
|
|
373
|
+
console.log(colors.yellow(' 4. Chrome DevTools로 브라우저를 제어했습니다'));
|
|
374
|
+
console.log(colors.purple(' 5. Context7으로 라이브러리를 검색했습니다'));
|
|
375
|
+
console.log(colors.peach(' 6. Simple Calculator로 덧셈 계산을 했습니다'));
|
|
376
|
+
console.log(colors.cyan(' 7. 사용을 마치고 모든 연결을 정리했습니다'));
|
|
258
377
|
console.log('');
|
|
259
378
|
process.exit(0);
|
|
260
379
|
}
|
|
261
380
|
|
|
262
381
|
// 메인 함수 실행
|
|
263
382
|
main().catch(error => {
|
|
264
|
-
console.error('\n❌ 치명적 오류:'
|
|
265
|
-
console.error(error.stack);
|
|
383
|
+
console.error(colors.pink.bold('\n❌ 치명적 오류: ') + colors.pink(error.message));
|
|
384
|
+
console.error(colors.pink.italic(error.stack));
|
|
266
385
|
process.exit(1);
|
|
267
386
|
});
|