@n0ts123/mcplink-core 0.0.12 → 0.0.13
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 +490 -709
- package/dist/index.d.ts +290 -415
- package/dist/index.js +473 -1557
- package/dist/index.js.map +1 -1
- package/package.json +2 -5
package/README.md
CHANGED
|
@@ -1,709 +1,490 @@
|
|
|
1
|
-
# @n0ts123/mcplink-core
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
[](https://www.npmjs.com/package/@n0ts123/mcplink-core)
|
|
6
|
-
[](https://github.com/n0tssss/MCPLink/blob/master/LICENSE)
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
## 🚀 快速开始
|
|
39
|
-
|
|
40
|
-
###
|
|
41
|
-
|
|
42
|
-
```typescript
|
|
43
|
-
import { MCPLink
|
|
44
|
-
|
|
45
|
-
//
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
mcpServers: {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
await
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
case
|
|
139
|
-
|
|
140
|
-
break
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
```
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
```typescript
|
|
493
|
-
// Stdio 模式(本地进程)
|
|
494
|
-
interface MCPServerConfigStdio {
|
|
495
|
-
type?: 'stdio'
|
|
496
|
-
command: string
|
|
497
|
-
args?: string[]
|
|
498
|
-
env?: Record<string, string>
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
// SSE 模式(远程服务)
|
|
502
|
-
interface MCPServerConfigSSE {
|
|
503
|
-
type: 'sse'
|
|
504
|
-
url: string
|
|
505
|
-
headers?: Record<string, string>
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
// Streamable HTTP 模式
|
|
509
|
-
interface MCPServerConfigStreamableHTTP {
|
|
510
|
-
type: 'streamable-http'
|
|
511
|
-
url: string
|
|
512
|
-
headers?: Record<string, string>
|
|
513
|
-
}
|
|
514
|
-
```
|
|
515
|
-
|
|
516
|
-
## 🤖 多模型支持
|
|
517
|
-
|
|
518
|
-
MCPLink 会根据模型自动选择最佳的调用方式:
|
|
519
|
-
|
|
520
|
-
| 模型 | 模式 | 说明 |
|
|
521
|
-
|------|------|------|
|
|
522
|
-
| GPT-4o, GPT-4, GPT-3.5 | 原生 | 使用 function calling |
|
|
523
|
-
| Claude-3, Claude-3.5 | 原生 | 使用 function calling |
|
|
524
|
-
| Gemini Flash/Pro | 原生 | 使用 function calling |
|
|
525
|
-
| Mistral, Mixtral | 原生 | 使用 function calling |
|
|
526
|
-
| DeepSeek | Prompt-Based | 使用 prompt 引导 |
|
|
527
|
-
| Qwen, 通义千问 | Prompt-Based | 使用 prompt 引导 |
|
|
528
|
-
| Llama, Yi, GLM | Prompt-Based | 使用 prompt 引导 |
|
|
529
|
-
|
|
530
|
-
### OpenAI
|
|
531
|
-
|
|
532
|
-
```typescript
|
|
533
|
-
import { MCPLink, createOpenAI } from '@n0ts123/mcplink-core'
|
|
534
|
-
|
|
535
|
-
const openai = createOpenAI({ apiKey: process.env.OPENAI_API_KEY })
|
|
536
|
-
const agent = new MCPLink({ model: openai('gpt-4o') })
|
|
537
|
-
```
|
|
538
|
-
|
|
539
|
-
### Anthropic Claude
|
|
540
|
-
|
|
541
|
-
```typescript
|
|
542
|
-
import { MCPLink, createAnthropic } from '@n0ts123/mcplink-core'
|
|
543
|
-
|
|
544
|
-
const anthropic = createAnthropic({ apiKey: process.env.ANTHROPIC_API_KEY })
|
|
545
|
-
const agent = new MCPLink({ model: anthropic('claude-3-5-sonnet-20241022') })
|
|
546
|
-
```
|
|
547
|
-
|
|
548
|
-
### Google Gemini
|
|
549
|
-
|
|
550
|
-
> 需额外安装:`npm install @ai-sdk/google`
|
|
551
|
-
|
|
552
|
-
```typescript
|
|
553
|
-
import { MCPLink } from '@n0ts123/mcplink-core'
|
|
554
|
-
import { createGoogleGenerativeAI } from '@ai-sdk/google'
|
|
555
|
-
|
|
556
|
-
const google = createGoogleGenerativeAI({ apiKey: process.env.GOOGLE_API_KEY })
|
|
557
|
-
const agent = new MCPLink({ model: google('gemini-1.5-flash') })
|
|
558
|
-
```
|
|
559
|
-
|
|
560
|
-
### DeepSeek / 通义千问
|
|
561
|
-
|
|
562
|
-
```typescript
|
|
563
|
-
import { MCPLink, createOpenAI } from '@n0ts123/mcplink-core'
|
|
564
|
-
|
|
565
|
-
// DeepSeek
|
|
566
|
-
const deepseek = createOpenAI({
|
|
567
|
-
apiKey: process.env.DEEPSEEK_API_KEY,
|
|
568
|
-
baseURL: 'https://api.deepseek.com/v1',
|
|
569
|
-
})
|
|
570
|
-
const agent = new MCPLink({ model: deepseek('deepseek-chat') })
|
|
571
|
-
|
|
572
|
-
// 通义千问
|
|
573
|
-
const qwen = createOpenAI({
|
|
574
|
-
apiKey: process.env.QWEN_API_KEY,
|
|
575
|
-
baseURL: 'https://dashscope.aliyuncs.com/compatible-mode/v1',
|
|
576
|
-
})
|
|
577
|
-
const agent = new MCPLink({ model: qwen('qwen-plus') })
|
|
578
|
-
```
|
|
579
|
-
|
|
580
|
-
## 💬 多轮对话
|
|
581
|
-
|
|
582
|
-
```typescript
|
|
583
|
-
const history: Array<{ role: 'user' | 'assistant'; content: string }> = []
|
|
584
|
-
|
|
585
|
-
// 第一轮
|
|
586
|
-
let response = ''
|
|
587
|
-
for await (const event of agent.chatStream('帮我查订单')) {
|
|
588
|
-
if (event.type === MCPLinkEventType.TEXT_DELTA) {
|
|
589
|
-
response += event.data.content || ''
|
|
590
|
-
}
|
|
591
|
-
}
|
|
592
|
-
history.push({ role: 'user', content: '帮我查订单' })
|
|
593
|
-
history.push({ role: 'assistant', content: response })
|
|
594
|
-
|
|
595
|
-
// 第二轮(携带历史)
|
|
596
|
-
for await (const event of agent.chatStream('第一个订单的详情', { history })) {
|
|
597
|
-
// ...
|
|
598
|
-
}
|
|
599
|
-
```
|
|
600
|
-
|
|
601
|
-
## 🔧 工具过滤
|
|
602
|
-
|
|
603
|
-
```typescript
|
|
604
|
-
// 只允许使用特定工具
|
|
605
|
-
for await (const event of agent.chatStream('搜索产品', {
|
|
606
|
-
allowedTools: ['search_products', 'get_product_details'],
|
|
607
|
-
})) {
|
|
608
|
-
// 只会调用指定的工具
|
|
609
|
-
}
|
|
610
|
-
```
|
|
611
|
-
|
|
612
|
-
## 🎯 即时结果
|
|
613
|
-
|
|
614
|
-
当 MCP 工具返回特定格式数据时,可立即推送给前端:
|
|
615
|
-
|
|
616
|
-
```typescript
|
|
617
|
-
const agent = new MCPLink({
|
|
618
|
-
model: openai('gpt-4o'),
|
|
619
|
-
mcpServers: { /* ... */ },
|
|
620
|
-
// 配置即时结果匹配器
|
|
621
|
-
immediateResultMatchers: [
|
|
622
|
-
{ type: 'card' }, // 匹配 { type: "card", ... }
|
|
623
|
-
{ type: 'product_list' }, // 匹配 { type: "product_list", ... }
|
|
624
|
-
],
|
|
625
|
-
})
|
|
626
|
-
|
|
627
|
-
for await (const event of agent.chatStream('搜索产品')) {
|
|
628
|
-
if (event.type === MCPLinkEventType.IMMEDIATE_RESULT) {
|
|
629
|
-
// 立即展示卡片/特殊格式数据
|
|
630
|
-
showCard(event.data.immediateResult)
|
|
631
|
-
}
|
|
632
|
-
}
|
|
633
|
-
```
|
|
634
|
-
|
|
635
|
-
## 📋 事件类型
|
|
636
|
-
|
|
637
|
-
| 事件 | 说明 | 数据 |
|
|
638
|
-
|------|------|------|
|
|
639
|
-
| `iteration_start` | 迭代开始 | `{ iteration, maxIterations }` |
|
|
640
|
-
| `iteration_end` | 迭代结束 | `{ iteration }` |
|
|
641
|
-
| `thinking_start` | 思考开始 | `{}` |
|
|
642
|
-
| `thinking_delta` | 思考内容 | `{ content }` |
|
|
643
|
-
| `thinking_end` | 思考结束 | `{}` |
|
|
644
|
-
| `thinking_content` | 完整思考内容 | `{ content }` |
|
|
645
|
-
| `text_start` | 文本开始 | `{}` |
|
|
646
|
-
| `text_delta` | 文本内容 | `{ content }` |
|
|
647
|
-
| `text_end` | 文本结束 | `{}` |
|
|
648
|
-
| `tool_call_start` | 工具调用开始 | `{ toolName, toolCallId, toolArgs }` |
|
|
649
|
-
| `tool_call_delta` | 工具参数流式 | `{ toolCallId, argsTextDelta }` |
|
|
650
|
-
| `tool_executing` | 工具执行中 | `{ toolName, toolCallId, toolArgs }` |
|
|
651
|
-
| `tool_result` | 工具结果 | `{ toolName, toolResult, toolCallId, duration, isError }` |
|
|
652
|
-
| `immediate_result` | 即时结果 | `{ toolName, toolCallId, immediateResult }` |
|
|
653
|
-
| `complete` | 完成 | `{ totalDuration, totalIterations }` |
|
|
654
|
-
| `error` | 错误 | `{ error }` |
|
|
655
|
-
|
|
656
|
-
## 🔧 手动工具管理
|
|
657
|
-
|
|
658
|
-
```typescript
|
|
659
|
-
// 获取所有可用工具
|
|
660
|
-
const tools = agent.getTools()
|
|
661
|
-
|
|
662
|
-
// 手动调用工具
|
|
663
|
-
const result = await agent.callTool('search_products', { keyword: 'test' })
|
|
664
|
-
|
|
665
|
-
// 获取 MCP 服务器状态
|
|
666
|
-
const statuses = agent.getMCPServerStatuses()
|
|
667
|
-
|
|
668
|
-
// 手动控制 MCP 服务器
|
|
669
|
-
await agent.startMCPServer('myServer')
|
|
670
|
-
await agent.stopMCPServer('myServer')
|
|
671
|
-
```
|
|
672
|
-
|
|
673
|
-
## 📝 TypeScript 类型
|
|
674
|
-
|
|
675
|
-
```typescript
|
|
676
|
-
import type {
|
|
677
|
-
MCPLinkConfig,
|
|
678
|
-
MCPServerConfig,
|
|
679
|
-
MCPServerConfigStdio,
|
|
680
|
-
MCPServerConfigSSE,
|
|
681
|
-
MCPServerConfigStreamableHTTP,
|
|
682
|
-
MCPLinkEvent,
|
|
683
|
-
MCPLinkEventData,
|
|
684
|
-
MCPTool,
|
|
685
|
-
MCPServerStatus,
|
|
686
|
-
ChatResult,
|
|
687
|
-
ChatCallbacks,
|
|
688
|
-
ImmediateResultMatcher,
|
|
689
|
-
} from '@n0ts123/mcplink-core'
|
|
690
|
-
|
|
691
|
-
import { MCPLinkEventType } from '@n0ts123/mcplink-core'
|
|
692
|
-
```
|
|
693
|
-
|
|
694
|
-
## 📋 环境要求
|
|
695
|
-
|
|
696
|
-
- **Node.js**: >= 18.0.0
|
|
697
|
-
- **模块系统**: ES Module(推荐)或 CommonJS(需使用动态 import)
|
|
698
|
-
|
|
699
|
-
## 🔗 相关链接
|
|
700
|
-
|
|
701
|
-
- [GitHub 仓库](https://github.com/n0tssss/MCPLink)
|
|
702
|
-
- [完整文档](https://github.com/n0tssss/MCPLink#readme)
|
|
703
|
-
- [问题反馈](https://github.com/n0tssss/MCPLink/issues)
|
|
704
|
-
- [MCP 协议规范](https://modelcontextprotocol.io/)
|
|
705
|
-
- [Vercel AI SDK](https://sdk.vercel.ai/)
|
|
706
|
-
|
|
707
|
-
## 📄 许可证
|
|
708
|
-
|
|
709
|
-
MIT License © [n0tssss](https://github.com/n0tssss)
|
|
1
|
+
# @n0ts123/mcplink-core
|
|
2
|
+
|
|
3
|
+
更方便的在代码里集成 MCP 工具直接让 AI 使用。
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@n0ts123/mcplink-core)
|
|
6
|
+
[](https://github.com/n0tssss/MCPLink/blob/master/LICENSE)
|
|
7
|
+
|
|
8
|
+
## 这是什么
|
|
9
|
+
|
|
10
|
+
用代码让 AI 调用 [MCP](https://modelcontextprotocol.io/) 工具,自动完成多步任务。
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
你:"帮我查一下最近订单"
|
|
14
|
+
AI:调用 get_orders 工具 → 收到结果 → "您有3个订单..."
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
**特点**:流式响应、支持任意 AI 参数、你自己掌控消息历史。
|
|
18
|
+
|
|
19
|
+
## 安装
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install @n0ts123/mcplink-core
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## 用法
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
# npm
|
|
29
|
+
npm install @n0ts123/mcplink-core
|
|
30
|
+
|
|
31
|
+
# pnpm
|
|
32
|
+
pnpm add @n0ts123/mcplink-core
|
|
33
|
+
|
|
34
|
+
# yarn
|
|
35
|
+
yarn add @n0ts123/mcplink-core
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## 🚀 快速开始
|
|
39
|
+
|
|
40
|
+
### 基础用法
|
|
41
|
+
|
|
42
|
+
```typescript
|
|
43
|
+
import { MCPLink } from '@n0ts123/mcplink-core'
|
|
44
|
+
|
|
45
|
+
// 创建 MCPLink 实例
|
|
46
|
+
const mcpLink = new MCPLink({
|
|
47
|
+
// AI 配置(OpenAI 兼容格式)
|
|
48
|
+
ai: {
|
|
49
|
+
baseURL: 'https://api.openai.com/v1',
|
|
50
|
+
apiKey: process.env.OPENAI_API_KEY,
|
|
51
|
+
model: 'gpt-4o',
|
|
52
|
+
// 支持任意自定义参数
|
|
53
|
+
temperature: 0.7,
|
|
54
|
+
enable_thinking: false,
|
|
55
|
+
},
|
|
56
|
+
// MCP 服务器配置
|
|
57
|
+
mcpServers: {
|
|
58
|
+
myTools: {
|
|
59
|
+
type: 'stdio',
|
|
60
|
+
command: 'node',
|
|
61
|
+
args: ['./my-mcp-server.js'],
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
// 初始化
|
|
67
|
+
await mcpLink.initialize()
|
|
68
|
+
|
|
69
|
+
// 发起对话(用户自己处理流式响应)
|
|
70
|
+
for await (const event of mcpLink.chatStream([
|
|
71
|
+
{ role: 'user', content: '你好' }
|
|
72
|
+
])) {
|
|
73
|
+
switch (event.type) {
|
|
74
|
+
case 'text':
|
|
75
|
+
process.stdout.write(event.content)
|
|
76
|
+
break
|
|
77
|
+
case 'tool_call':
|
|
78
|
+
console.log('调用工具:', event.toolCall.name)
|
|
79
|
+
break
|
|
80
|
+
case 'done':
|
|
81
|
+
console.log('\n完成!')
|
|
82
|
+
break
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
await mcpLink.close()
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### 使用标准事件流
|
|
90
|
+
|
|
91
|
+
如果你希望使用更丰富的标准事件,可以使用 `toStandardStream`:
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
import { MCPLink, toStandardStream, type StandardStreamEvent } from '@n0ts123/mcplink-core'
|
|
95
|
+
|
|
96
|
+
const mcpLink = new MCPLink({
|
|
97
|
+
ai: { baseURL: '...', apiKey: '...', model: 'gpt-4o' },
|
|
98
|
+
mcpServers: { /* ... */ },
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
await mcpLink.initialize()
|
|
102
|
+
|
|
103
|
+
// 创建底层流
|
|
104
|
+
async function* rawStream() {
|
|
105
|
+
for await (const event of mcpLink.chatStream([
|
|
106
|
+
{ role: 'user', content: '查询订单' }
|
|
107
|
+
])) {
|
|
108
|
+
yield event
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// 转换为标准事件流
|
|
113
|
+
for await (const event of toStandardStream(rawStream(), {
|
|
114
|
+
maxIterations: 10,
|
|
115
|
+
executeTool: async (name, args) => {
|
|
116
|
+
return await mcpLink.callTool(name, args)
|
|
117
|
+
},
|
|
118
|
+
})) {
|
|
119
|
+
switch (event.type) {
|
|
120
|
+
case 'text_start':
|
|
121
|
+
console.log('开始输出文本...')
|
|
122
|
+
break
|
|
123
|
+
case 'text_delta':
|
|
124
|
+
process.stdout.write(event.content)
|
|
125
|
+
break
|
|
126
|
+
case 'text_end':
|
|
127
|
+
console.log('\n文本输出结束')
|
|
128
|
+
break
|
|
129
|
+
case 'tool_call_start':
|
|
130
|
+
console.log(`调用工具: ${event.toolName}`)
|
|
131
|
+
break
|
|
132
|
+
case 'tool_executing':
|
|
133
|
+
console.log(`执行中: ${event.toolName}...`)
|
|
134
|
+
break
|
|
135
|
+
case 'tool_result':
|
|
136
|
+
console.log(`结果: ${JSON.stringify(event.toolResult)}`)
|
|
137
|
+
break
|
|
138
|
+
case 'complete':
|
|
139
|
+
console.log(`完成! 耗时: ${event.totalDuration}ms`)
|
|
140
|
+
break
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## ⚙️ 配置选项
|
|
146
|
+
|
|
147
|
+
### MCPLinkConfig
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
interface MCPLinkConfig {
|
|
151
|
+
/** AI 配置(OpenAI 兼容格式) */
|
|
152
|
+
ai: {
|
|
153
|
+
baseURL: string
|
|
154
|
+
apiKey: string
|
|
155
|
+
model: string
|
|
156
|
+
// 支持任意自定义参数
|
|
157
|
+
temperature?: number
|
|
158
|
+
max_tokens?: number
|
|
159
|
+
enable_thinking?: boolean
|
|
160
|
+
// 其他参数...
|
|
161
|
+
[key: string]: unknown
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/** 适配器类型(默认 'openai') */
|
|
165
|
+
adapter?: 'openai' | AIAdapter
|
|
166
|
+
|
|
167
|
+
/** MCP 服务器配置 */
|
|
168
|
+
mcpServers?: Record<string, MCPServerConfig>
|
|
169
|
+
|
|
170
|
+
/** 最大迭代次数(默认 10) */
|
|
171
|
+
maxIterations?: number
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### 完全自定义参数
|
|
176
|
+
|
|
177
|
+
所有在 `ai` 中的参数都会原封不动传递给 AI 提供商:
|
|
178
|
+
|
|
179
|
+
```typescript
|
|
180
|
+
const mcpLink = new MCPLink({
|
|
181
|
+
ai: {
|
|
182
|
+
baseURL: 'https://dashscope.aliyuncs.com/compatible-mode/v1',
|
|
183
|
+
apiKey: process.env.QWEN_API_KEY,
|
|
184
|
+
model: 'qwen3.5-plus',
|
|
185
|
+
// 完全自定义参数
|
|
186
|
+
temperature: 0.8,
|
|
187
|
+
max_tokens: 2048,
|
|
188
|
+
enable_thinking: true, // Qwen 思考模式
|
|
189
|
+
top_p: 0.9,
|
|
190
|
+
// 任意其他参数...
|
|
191
|
+
custom_param: 'value',
|
|
192
|
+
},
|
|
193
|
+
mcpServers: { /* ... */ },
|
|
194
|
+
})
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### MCP 服务器配置
|
|
198
|
+
|
|
199
|
+
```typescript
|
|
200
|
+
// Stdio 模式(本地进程)
|
|
201
|
+
interface MCPServerConfigStdio {
|
|
202
|
+
type: 'stdio'
|
|
203
|
+
command: string
|
|
204
|
+
args?: string[]
|
|
205
|
+
env?: Record<string, string>
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// Streamable HTTP 模式
|
|
209
|
+
interface MCPServerConfigStreamableHTTP {
|
|
210
|
+
type: 'streamable-http'
|
|
211
|
+
url: string
|
|
212
|
+
headers?: Record<string, string>
|
|
213
|
+
}
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## 🎯 核心概念
|
|
217
|
+
|
|
218
|
+
### 底层事件(Raw Events)
|
|
219
|
+
|
|
220
|
+
MCPLink 返回最原始的 AI 事件:
|
|
221
|
+
|
|
222
|
+
```typescript
|
|
223
|
+
type AIStreamEvent =
|
|
224
|
+
| { type: 'text'; content: string }
|
|
225
|
+
| { type: 'tool_call'; toolCall: { id: string; name: string; arguments: Record<string, unknown> } }
|
|
226
|
+
| { type: 'done' }
|
|
227
|
+
| { type: 'error'; error: Error }
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
**设计哲学**:用户自己处理 AI 响应,框架不做多余的事情。
|
|
231
|
+
|
|
232
|
+
### 标准事件流(Standard Events)
|
|
233
|
+
|
|
234
|
+
提供可选的 `toStandardStream` 转换器,将底层事件转换为更丰富的标准事件:
|
|
235
|
+
|
|
236
|
+
```typescript
|
|
237
|
+
type StandardStreamEvent =
|
|
238
|
+
| { type: 'text_start' }
|
|
239
|
+
| { type: 'text_delta'; content: string }
|
|
240
|
+
| { type: 'text_end' }
|
|
241
|
+
| { type: 'thinking_start' }
|
|
242
|
+
| { type: 'thinking_delta'; content: string }
|
|
243
|
+
| { type: 'thinking_end' }
|
|
244
|
+
| { type: 'tool_call_start'; toolCallId: string; toolName: string; toolArgs: Record<string, unknown> }
|
|
245
|
+
| { type: 'tool_executing'; toolCallId: string; toolName: string }
|
|
246
|
+
| { type: 'tool_result'; toolCallId: string; toolName: string; toolResult: unknown; duration: number; isError?: boolean }
|
|
247
|
+
| { type: 'complete'; totalIterations: number; totalDuration: number }
|
|
248
|
+
| { type: 'error'; error: Error }
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
## 🤖 多模型支持
|
|
252
|
+
|
|
253
|
+
MCPLink 使用 OpenAI 兼容格式,支持任意 AI 提供商:
|
|
254
|
+
|
|
255
|
+
### OpenAI
|
|
256
|
+
|
|
257
|
+
```typescript
|
|
258
|
+
const mcpLink = new MCPLink({
|
|
259
|
+
ai: {
|
|
260
|
+
baseURL: 'https://api.openai.com/v1',
|
|
261
|
+
apiKey: process.env.OPENAI_API_KEY,
|
|
262
|
+
model: 'gpt-4o',
|
|
263
|
+
},
|
|
264
|
+
})
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### DeepSeek
|
|
268
|
+
|
|
269
|
+
```typescript
|
|
270
|
+
const mcpLink = new MCPLink({
|
|
271
|
+
ai: {
|
|
272
|
+
baseURL: 'https://api.deepseek.com/v1',
|
|
273
|
+
apiKey: process.env.DEEPSEEK_API_KEY,
|
|
274
|
+
model: 'deepseek-chat',
|
|
275
|
+
},
|
|
276
|
+
})
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
### 通义千问 (Qwen)
|
|
280
|
+
|
|
281
|
+
```typescript
|
|
282
|
+
const mcpLink = new MCPLink({
|
|
283
|
+
ai: {
|
|
284
|
+
baseURL: 'https://dashscope.aliyuncs.com/compatible-mode/v1',
|
|
285
|
+
apiKey: process.env.QWEN_API_KEY,
|
|
286
|
+
model: 'qwen3.5-plus',
|
|
287
|
+
enable_thinking: false, // 关闭思考
|
|
288
|
+
},
|
|
289
|
+
})
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
### Claude (OpenAI 兼容)
|
|
293
|
+
|
|
294
|
+
```typescript
|
|
295
|
+
const mcpLink = new MCPLink({
|
|
296
|
+
ai: {
|
|
297
|
+
baseURL: 'https://api.anthropic.com/v1',
|
|
298
|
+
apiKey: process.env.ANTHROPIC_API_KEY,
|
|
299
|
+
model: 'claude-3-5-sonnet',
|
|
300
|
+
},
|
|
301
|
+
})
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
### Gemini (OpenAI 兼容)
|
|
305
|
+
|
|
306
|
+
```typescript
|
|
307
|
+
const mcpLink = new MCPLink({
|
|
308
|
+
ai: {
|
|
309
|
+
baseURL: 'https://generativelanguage.googleapis.com/v1beta/openai',
|
|
310
|
+
apiKey: process.env.GOOGLE_API_KEY,
|
|
311
|
+
model: 'gemini-1.5-flash',
|
|
312
|
+
},
|
|
313
|
+
})
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
## 🛠️ API 参考
|
|
317
|
+
|
|
318
|
+
### MCPLink
|
|
319
|
+
|
|
320
|
+
```typescript
|
|
321
|
+
class MCPLink {
|
|
322
|
+
constructor(config: MCPLinkConfig)
|
|
323
|
+
|
|
324
|
+
/** 初始化 MCP 连接 */
|
|
325
|
+
async initialize(): Promise<void>
|
|
326
|
+
|
|
327
|
+
/** 关闭所有连接 */
|
|
328
|
+
async close(): Promise<void>
|
|
329
|
+
|
|
330
|
+
/** 发起对话(非流式) */
|
|
331
|
+
async chat(options: ChatOptions): Promise<ChatResult>
|
|
332
|
+
|
|
333
|
+
/** 发起对话(流式,返回底层事件) */
|
|
334
|
+
async chatStream(
|
|
335
|
+
messages: Message[],
|
|
336
|
+
onStream?: (event: AIStreamEvent) => boolean | void
|
|
337
|
+
): Promise<ChatResult>
|
|
338
|
+
|
|
339
|
+
/** 获取所有可用工具 */
|
|
340
|
+
getTools(): MCPTool[]
|
|
341
|
+
|
|
342
|
+
/** 调用指定工具 */
|
|
343
|
+
async callTool(toolName: string, args: Record<string, unknown>): Promise<unknown>
|
|
344
|
+
|
|
345
|
+
/** 获取 MCP 服务器状态 */
|
|
346
|
+
getMCPServerStatuses(): MCPServerStatus[]
|
|
347
|
+
|
|
348
|
+
/** 启动/停止 MCP 服务器 */
|
|
349
|
+
async startMCPServer(id: string): Promise<void>
|
|
350
|
+
async stopMCPServer(id: string): Promise<void>
|
|
351
|
+
}
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
### toStandardStream
|
|
355
|
+
|
|
356
|
+
将底层事件流转换为标准事件流:
|
|
357
|
+
|
|
358
|
+
```typescript
|
|
359
|
+
async function* toStandardStream(
|
|
360
|
+
rawStream: AsyncGenerator<AIStreamEvent>,
|
|
361
|
+
options: {
|
|
362
|
+
maxIterations?: number
|
|
363
|
+
executeTool: (name: string, args: Record<string, unknown>) => Promise<unknown>
|
|
364
|
+
onRawEvent?: (event: AIStreamEvent) => boolean | void
|
|
365
|
+
}
|
|
366
|
+
): AsyncGenerator<StandardStreamEvent>
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
### collectStandardResponse
|
|
370
|
+
|
|
371
|
+
收集流式响应为完整结果(非流式场景):
|
|
372
|
+
|
|
373
|
+
```typescript
|
|
374
|
+
async function collectStandardResponse(
|
|
375
|
+
stream: AsyncGenerator<StandardStreamEvent>
|
|
376
|
+
): Promise<{
|
|
377
|
+
content: string
|
|
378
|
+
toolCalls: Array<{
|
|
379
|
+
id: string
|
|
380
|
+
name: string
|
|
381
|
+
arguments: Record<string, unknown>
|
|
382
|
+
result?: unknown
|
|
383
|
+
duration?: number
|
|
384
|
+
isError?: boolean
|
|
385
|
+
}>
|
|
386
|
+
iterations: number
|
|
387
|
+
duration: number
|
|
388
|
+
}>
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
## 📋 事件类型对比
|
|
392
|
+
|
|
393
|
+
| 底层事件 | 标准事件 | 说明 |
|
|
394
|
+
|---------|---------|------|
|
|
395
|
+
| `text` | `text_start` / `text_delta` / `text_end` | 文本输出拆分 |
|
|
396
|
+
| `tool_call` | `tool_call_start` / `tool_executing` / `tool_result` | 工具调用拆分 |
|
|
397
|
+
| - | `thinking_start` / `thinking_delta` / `thinking_end` | 思考过程(可选) |
|
|
398
|
+
| `done` | `complete` | 完成事件 |
|
|
399
|
+
| `error` | `error` | 错误事件 |
|
|
400
|
+
|
|
401
|
+
## 🏗️ 架构设计
|
|
402
|
+
|
|
403
|
+
```
|
|
404
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
405
|
+
│ 你的应用 │
|
|
406
|
+
│ ┌─────────────────┐ ┌─────────────────────────────────┐ │
|
|
407
|
+
│ │ 底层事件流处理 │ │ 标准事件流处理 │ │
|
|
408
|
+
│ │ (完全自定义) │ │ (使用 toStandardStream) │ │
|
|
409
|
+
│ └────────┬────────┘ └───────────────┬─────────────────┘ │
|
|
410
|
+
│ │ │ │
|
|
411
|
+
│ ▼ ▼ │
|
|
412
|
+
│ ┌──────────────────────────────────────────────────────┐ │
|
|
413
|
+
│ │ MCPLink Core │ │
|
|
414
|
+
│ │ ┌─────────────────────────────────────────────────┐ │ │
|
|
415
|
+
│ │ │ HTTP Client (axios + SSE) │ │ │
|
|
416
|
+
│ │ └─────────────────────┬───────────────────────────┘ │ │
|
|
417
|
+
│ │ │ │ │
|
|
418
|
+
│ │ ┌────▼────┐ │ │
|
|
419
|
+
│ │ │ OpenAI │ ← 可扩展其他适配器 │ │
|
|
420
|
+
│ │ │ Adapter │ │ │
|
|
421
|
+
│ │ └────┬────┘ │ │
|
|
422
|
+
│ │ │ │ │
|
|
423
|
+
│ │ ┌─────────────────────▼───────────────────────────┐ │ │
|
|
424
|
+
│ │ │ MCP Manager │ │ │
|
|
425
|
+
│ │ └─────────────────────┬───────────────────────────┘ │ │
|
|
426
|
+
│ └────────────────────────┼──────────────────────────────┘ │
|
|
427
|
+
└──────────────────────────┼──────────────────────────────────┘
|
|
428
|
+
│
|
|
429
|
+
┌────────────────┼────────────────┐
|
|
430
|
+
▼ ▼ ▼
|
|
431
|
+
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
|
432
|
+
│ MCP Server │ │ MCP Server │ │ MCP Server │
|
|
433
|
+
│ (stdio) │ │ (streamable-http)│ │ (stdio) │
|
|
434
|
+
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
**设计原则**:
|
|
438
|
+
- **最小侵入**:只负责 AI 调用和 MCP 工具执行
|
|
439
|
+
- **用户掌控**:用户自己处理响应,维护消息历史
|
|
440
|
+
- **完全透明**:所有 AI 参数原封透传
|
|
441
|
+
- **可选增强**:标准事件流是可选的转换层
|
|
442
|
+
|
|
443
|
+
## 📦 导出列表
|
|
444
|
+
|
|
445
|
+
```typescript
|
|
446
|
+
// 核心类
|
|
447
|
+
export { MCPLink } from './MCPLink.js'
|
|
448
|
+
export { MCPManager } from './MCPManager.js'
|
|
449
|
+
export { HttpClient } from './http-client.js'
|
|
450
|
+
|
|
451
|
+
// 适配器
|
|
452
|
+
export { OpenAIAdapter, openaiAdapter } from './adapters/openai.js'
|
|
453
|
+
|
|
454
|
+
// 标准事件流
|
|
455
|
+
export {
|
|
456
|
+
toStandardStream,
|
|
457
|
+
collectStandardResponse,
|
|
458
|
+
type StandardStreamEvent,
|
|
459
|
+
type StandardStreamOptions,
|
|
460
|
+
type StandardResponse,
|
|
461
|
+
} from './standard-stream.js'
|
|
462
|
+
|
|
463
|
+
// 类型
|
|
464
|
+
export type {
|
|
465
|
+
MCPLinkConfig,
|
|
466
|
+
MCPServerConfig,
|
|
467
|
+
AIRequestConfig,
|
|
468
|
+
Message,
|
|
469
|
+
AIStreamEvent,
|
|
470
|
+
ChatResult,
|
|
471
|
+
MCPTool,
|
|
472
|
+
MCPServerStatus,
|
|
473
|
+
} from './types.js'
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
## 📝 环境要求
|
|
477
|
+
|
|
478
|
+
- **Node.js**: >= 18.0.0
|
|
479
|
+
- **模块系统**: ES Module
|
|
480
|
+
|
|
481
|
+
## 🔗 相关链接
|
|
482
|
+
|
|
483
|
+
- [GitHub 仓库](https://github.com/n0tssss/MCPLink)
|
|
484
|
+
- [完整文档](https://github.com/n0tssss/MCPLink#readme)
|
|
485
|
+
- [问题反馈](https://github.com/n0tssss/MCPLink/issues)
|
|
486
|
+
- [MCP 协议规范](https://modelcontextprotocol.io/)
|
|
487
|
+
|
|
488
|
+
## 📄 许可证
|
|
489
|
+
|
|
490
|
+
MIT License © [n0tssss](https://github.com/n0tssss)
|