agentdog 1.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 (291) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +244 -0
  3. package/dist/adapters/adapter-factory.d.ts +21 -0
  4. package/dist/adapters/adapter-factory.d.ts.map +1 -0
  5. package/dist/adapters/adapter-factory.js +157 -0
  6. package/dist/adapters/adapter-factory.js.map +1 -0
  7. package/dist/adapters/http-sse-adapter.d.ts +49 -0
  8. package/dist/adapters/http-sse-adapter.d.ts.map +1 -0
  9. package/dist/adapters/http-sse-adapter.js +485 -0
  10. package/dist/adapters/http-sse-adapter.js.map +1 -0
  11. package/dist/adapters/stdio-adapter.d.ts +69 -0
  12. package/dist/adapters/stdio-adapter.d.ts.map +1 -0
  13. package/dist/adapters/stdio-adapter.js +664 -0
  14. package/dist/adapters/stdio-adapter.js.map +1 -0
  15. package/dist/adapters/streamable-http-adapter.d.ts +38 -0
  16. package/dist/adapters/streamable-http-adapter.d.ts.map +1 -0
  17. package/dist/adapters/streamable-http-adapter.js +321 -0
  18. package/dist/adapters/streamable-http-adapter.js.map +1 -0
  19. package/dist/ai-gateway/anthropic-errors.d.ts +4 -0
  20. package/dist/ai-gateway/anthropic-errors.d.ts.map +1 -0
  21. package/dist/ai-gateway/anthropic-errors.js +17 -0
  22. package/dist/ai-gateway/anthropic-errors.js.map +1 -0
  23. package/dist/ai-gateway/auth.d.ts +3 -0
  24. package/dist/ai-gateway/auth.d.ts.map +1 -0
  25. package/dist/ai-gateway/auth.js +14 -0
  26. package/dist/ai-gateway/auth.js.map +1 -0
  27. package/dist/ai-gateway/auth.test.d.ts +2 -0
  28. package/dist/ai-gateway/auth.test.d.ts.map +1 -0
  29. package/dist/ai-gateway/auth.test.js +57 -0
  30. package/dist/ai-gateway/auth.test.js.map +1 -0
  31. package/dist/ai-gateway/count-tokens.d.ts +5 -0
  32. package/dist/ai-gateway/count-tokens.d.ts.map +1 -0
  33. package/dist/ai-gateway/count-tokens.js +37 -0
  34. package/dist/ai-gateway/count-tokens.js.map +1 -0
  35. package/dist/ai-gateway/count-tokens.test.d.ts +2 -0
  36. package/dist/ai-gateway/count-tokens.test.d.ts.map +1 -0
  37. package/dist/ai-gateway/count-tokens.test.js +19 -0
  38. package/dist/ai-gateway/count-tokens.test.js.map +1 -0
  39. package/dist/ai-gateway/dialects.d.ts +4 -0
  40. package/dist/ai-gateway/dialects.d.ts.map +1 -0
  41. package/dist/ai-gateway/dialects.js +15 -0
  42. package/dist/ai-gateway/dialects.js.map +1 -0
  43. package/dist/ai-gateway/gateway-server.d.ts +15 -0
  44. package/dist/ai-gateway/gateway-server.d.ts.map +1 -0
  45. package/dist/ai-gateway/gateway-server.js +121 -0
  46. package/dist/ai-gateway/gateway-server.js.map +1 -0
  47. package/dist/ai-gateway/integration.test.d.ts +2 -0
  48. package/dist/ai-gateway/integration.test.d.ts.map +1 -0
  49. package/dist/ai-gateway/integration.test.js +205 -0
  50. package/dist/ai-gateway/integration.test.js.map +1 -0
  51. package/dist/ai-gateway/ir/anthropic-in.d.ts +3 -0
  52. package/dist/ai-gateway/ir/anthropic-in.d.ts.map +1 -0
  53. package/dist/ai-gateway/ir/anthropic-in.js +121 -0
  54. package/dist/ai-gateway/ir/anthropic-in.js.map +1 -0
  55. package/dist/ai-gateway/ir/anthropic-in.test.d.ts +2 -0
  56. package/dist/ai-gateway/ir/anthropic-in.test.d.ts.map +1 -0
  57. package/dist/ai-gateway/ir/anthropic-in.test.js +93 -0
  58. package/dist/ai-gateway/ir/anthropic-in.test.js.map +1 -0
  59. package/dist/ai-gateway/ir/anthropic-sse.d.ts +22 -0
  60. package/dist/ai-gateway/ir/anthropic-sse.d.ts.map +1 -0
  61. package/dist/ai-gateway/ir/anthropic-sse.js +200 -0
  62. package/dist/ai-gateway/ir/anthropic-sse.js.map +1 -0
  63. package/dist/ai-gateway/ir/anthropic-sse.test.d.ts +2 -0
  64. package/dist/ai-gateway/ir/anthropic-sse.test.d.ts.map +1 -0
  65. package/dist/ai-gateway/ir/anthropic-sse.test.js +101 -0
  66. package/dist/ai-gateway/ir/anthropic-sse.test.js.map +1 -0
  67. package/dist/ai-gateway/ir/gemini-out.d.ts +20 -0
  68. package/dist/ai-gateway/ir/gemini-out.d.ts.map +1 -0
  69. package/dist/ai-gateway/ir/gemini-out.js +218 -0
  70. package/dist/ai-gateway/ir/gemini-out.js.map +1 -0
  71. package/dist/ai-gateway/ir/gemini-out.test.d.ts +2 -0
  72. package/dist/ai-gateway/ir/gemini-out.test.d.ts.map +1 -0
  73. package/dist/ai-gateway/ir/gemini-out.test.js +125 -0
  74. package/dist/ai-gateway/ir/gemini-out.test.js.map +1 -0
  75. package/dist/ai-gateway/ir/openai-out.d.ts +17 -0
  76. package/dist/ai-gateway/ir/openai-out.d.ts.map +1 -0
  77. package/dist/ai-gateway/ir/openai-out.js +226 -0
  78. package/dist/ai-gateway/ir/openai-out.js.map +1 -0
  79. package/dist/ai-gateway/ir/openai-out.test.d.ts +2 -0
  80. package/dist/ai-gateway/ir/openai-out.test.d.ts.map +1 -0
  81. package/dist/ai-gateway/ir/openai-out.test.js +144 -0
  82. package/dist/ai-gateway/ir/openai-out.test.js.map +1 -0
  83. package/dist/ai-gateway/ir/types.d.ts +77 -0
  84. package/dist/ai-gateway/ir/types.d.ts.map +1 -0
  85. package/dist/ai-gateway/ir/types.js +4 -0
  86. package/dist/ai-gateway/ir/types.js.map +1 -0
  87. package/dist/ai-gateway/ir-channel.d.ts +15 -0
  88. package/dist/ai-gateway/ir-channel.d.ts.map +1 -0
  89. package/dist/ai-gateway/ir-channel.js +120 -0
  90. package/dist/ai-gateway/ir-channel.js.map +1 -0
  91. package/dist/ai-gateway/model-router.d.ts +11 -0
  92. package/dist/ai-gateway/model-router.d.ts.map +1 -0
  93. package/dist/ai-gateway/model-router.js +27 -0
  94. package/dist/ai-gateway/model-router.js.map +1 -0
  95. package/dist/ai-gateway/model-router.test.d.ts +2 -0
  96. package/dist/ai-gateway/model-router.test.d.ts.map +1 -0
  97. package/dist/ai-gateway/model-router.test.js +43 -0
  98. package/dist/ai-gateway/model-router.test.js.map +1 -0
  99. package/dist/ai-gateway/passthrough.d.ts +9 -0
  100. package/dist/ai-gateway/passthrough.d.ts.map +1 -0
  101. package/dist/ai-gateway/passthrough.js +81 -0
  102. package/dist/ai-gateway/passthrough.js.map +1 -0
  103. package/dist/ai-gateway/passthrough.test.d.ts +2 -0
  104. package/dist/ai-gateway/passthrough.test.d.ts.map +1 -0
  105. package/dist/ai-gateway/passthrough.test.js +108 -0
  106. package/dist/ai-gateway/passthrough.test.js.map +1 -0
  107. package/dist/ai-gateway/upstream/model-lister.d.ts +13 -0
  108. package/dist/ai-gateway/upstream/model-lister.d.ts.map +1 -0
  109. package/dist/ai-gateway/upstream/model-lister.js +61 -0
  110. package/dist/ai-gateway/upstream/model-lister.js.map +1 -0
  111. package/dist/ai-gateway/upstream/provider-client.d.ts +20 -0
  112. package/dist/ai-gateway/upstream/provider-client.d.ts.map +1 -0
  113. package/dist/ai-gateway/upstream/provider-client.js +76 -0
  114. package/dist/ai-gateway/upstream/provider-client.js.map +1 -0
  115. package/dist/ai-gateway/upstream/provider-client.test.d.ts +2 -0
  116. package/dist/ai-gateway/upstream/provider-client.test.d.ts.map +1 -0
  117. package/dist/ai-gateway/upstream/provider-client.test.js +69 -0
  118. package/dist/ai-gateway/upstream/provider-client.test.js.map +1 -0
  119. package/dist/cli/cli-main.d.ts +7 -0
  120. package/dist/cli/cli-main.d.ts.map +1 -0
  121. package/dist/cli/cli-main.js +116 -0
  122. package/dist/cli/cli-main.js.map +1 -0
  123. package/dist/cli/cli-router.d.ts +20 -0
  124. package/dist/cli/cli-router.d.ts.map +1 -0
  125. package/dist/cli/cli-router.js +271 -0
  126. package/dist/cli/cli-router.js.map +1 -0
  127. package/dist/cli/cli-utils.d.ts +30 -0
  128. package/dist/cli/cli-utils.d.ts.map +1 -0
  129. package/dist/cli/cli-utils.js +219 -0
  130. package/dist/cli/cli-utils.js.map +1 -0
  131. package/dist/cli/commands/audit-commands.d.ts +30 -0
  132. package/dist/cli/commands/audit-commands.d.ts.map +1 -0
  133. package/dist/cli/commands/audit-commands.js +417 -0
  134. package/dist/cli/commands/audit-commands.js.map +1 -0
  135. package/dist/cli/commands/autostart-command.d.ts +21 -0
  136. package/dist/cli/commands/autostart-command.d.ts.map +1 -0
  137. package/dist/cli/commands/autostart-command.js +243 -0
  138. package/dist/cli/commands/autostart-command.js.map +1 -0
  139. package/dist/cli/commands/autostart-command.test.d.ts +2 -0
  140. package/dist/cli/commands/autostart-command.test.d.ts.map +1 -0
  141. package/dist/cli/commands/autostart-command.test.js +35 -0
  142. package/dist/cli/commands/autostart-command.test.js.map +1 -0
  143. package/dist/cli/commands/config-commands.d.ts +30 -0
  144. package/dist/cli/commands/config-commands.d.ts.map +1 -0
  145. package/dist/cli/commands/config-commands.js +1013 -0
  146. package/dist/cli/commands/config-commands.js.map +1 -0
  147. package/dist/cli/commands/daemon-commands.d.ts +76 -0
  148. package/dist/cli/commands/daemon-commands.d.ts.map +1 -0
  149. package/dist/cli/commands/daemon-commands.js +451 -0
  150. package/dist/cli/commands/daemon-commands.js.map +1 -0
  151. package/dist/cli/commands/detect-commands.d.ts +17 -0
  152. package/dist/cli/commands/detect-commands.d.ts.map +1 -0
  153. package/dist/cli/commands/detect-commands.js +293 -0
  154. package/dist/cli/commands/detect-commands.js.map +1 -0
  155. package/dist/cli/commands/diagnose-commands.d.ts +19 -0
  156. package/dist/cli/commands/diagnose-commands.d.ts.map +1 -0
  157. package/dist/cli/commands/diagnose-commands.js +326 -0
  158. package/dist/cli/commands/diagnose-commands.js.map +1 -0
  159. package/dist/cli/commands/optimize-commands.d.ts +14 -0
  160. package/dist/cli/commands/optimize-commands.d.ts.map +1 -0
  161. package/dist/cli/commands/optimize-commands.js +189 -0
  162. package/dist/cli/commands/optimize-commands.js.map +1 -0
  163. package/dist/cli/commands/proxy-command.d.ts +27 -0
  164. package/dist/cli/commands/proxy-command.d.ts.map +1 -0
  165. package/dist/cli/commands/proxy-command.js +212 -0
  166. package/dist/cli/commands/proxy-command.js.map +1 -0
  167. package/dist/cli/commands/start-command.d.ts +22 -0
  168. package/dist/cli/commands/start-command.d.ts.map +1 -0
  169. package/dist/cli/commands/start-command.js +275 -0
  170. package/dist/cli/commands/start-command.js.map +1 -0
  171. package/dist/config/config-manager.d.ts +125 -0
  172. package/dist/config/config-manager.d.ts.map +1 -0
  173. package/dist/config/config-manager.js +569 -0
  174. package/dist/config/config-manager.js.map +1 -0
  175. package/dist/config/config-manager.test.d.ts +2 -0
  176. package/dist/config/config-manager.test.d.ts.map +1 -0
  177. package/dist/config/config-manager.test.js +209 -0
  178. package/dist/config/config-manager.test.js.map +1 -0
  179. package/dist/core/auto-config-generator.d.ts +55 -0
  180. package/dist/core/auto-config-generator.d.ts.map +1 -0
  181. package/dist/core/auto-config-generator.js +278 -0
  182. package/dist/core/auto-config-generator.js.map +1 -0
  183. package/dist/core/mcpdog-server.d.ts +49 -0
  184. package/dist/core/mcpdog-server.d.ts.map +1 -0
  185. package/dist/core/mcpdog-server.js +552 -0
  186. package/dist/core/mcpdog-server.js.map +1 -0
  187. package/dist/core/protocol-detector.d.ts +56 -0
  188. package/dist/core/protocol-detector.d.ts.map +1 -0
  189. package/dist/core/protocol-detector.js +365 -0
  190. package/dist/core/protocol-detector.js.map +1 -0
  191. package/dist/daemon/daemon-client.d.ts +34 -0
  192. package/dist/daemon/daemon-client.d.ts.map +1 -0
  193. package/dist/daemon/daemon-client.js +130 -0
  194. package/dist/daemon/daemon-client.js.map +1 -0
  195. package/dist/daemon/daemon-client.test.d.ts +2 -0
  196. package/dist/daemon/daemon-client.test.d.ts.map +1 -0
  197. package/dist/daemon/daemon-client.test.js +77 -0
  198. package/dist/daemon/daemon-client.test.js.map +1 -0
  199. package/dist/daemon/daemon-info.d.ts +7 -0
  200. package/dist/daemon/daemon-info.d.ts.map +1 -0
  201. package/dist/daemon/daemon-info.js +34 -0
  202. package/dist/daemon/daemon-info.js.map +1 -0
  203. package/dist/daemon/daemon-info.test.d.ts +2 -0
  204. package/dist/daemon/daemon-info.test.d.ts.map +1 -0
  205. package/dist/daemon/daemon-info.test.js +57 -0
  206. package/dist/daemon/daemon-info.test.js.map +1 -0
  207. package/dist/daemon/daemon-web-server.ai.test.d.ts +2 -0
  208. package/dist/daemon/daemon-web-server.ai.test.d.ts.map +1 -0
  209. package/dist/daemon/daemon-web-server.ai.test.js +119 -0
  210. package/dist/daemon/daemon-web-server.ai.test.js.map +1 -0
  211. package/dist/daemon/daemon-web-server.d.ts +59 -0
  212. package/dist/daemon/daemon-web-server.d.ts.map +1 -0
  213. package/dist/daemon/daemon-web-server.js +1236 -0
  214. package/dist/daemon/daemon-web-server.js.map +1 -0
  215. package/dist/daemon/daemon-web-server.test.d.ts +2 -0
  216. package/dist/daemon/daemon-web-server.test.d.ts.map +1 -0
  217. package/dist/daemon/daemon-web-server.test.js +93 -0
  218. package/dist/daemon/daemon-web-server.test.js.map +1 -0
  219. package/dist/daemon/mcpdog-daemon.d.ts +42 -0
  220. package/dist/daemon/mcpdog-daemon.d.ts.map +1 -0
  221. package/dist/daemon/mcpdog-daemon.js +302 -0
  222. package/dist/daemon/mcpdog-daemon.js.map +1 -0
  223. package/dist/daemon/stdio-proxy.d.ts +17 -0
  224. package/dist/daemon/stdio-proxy.d.ts.map +1 -0
  225. package/dist/daemon/stdio-proxy.js +143 -0
  226. package/dist/daemon/stdio-proxy.js.map +1 -0
  227. package/dist/index.d.ts +14 -0
  228. package/dist/index.d.ts.map +1 -0
  229. package/dist/index.js +198 -0
  230. package/dist/index.js.map +1 -0
  231. package/dist/intent-analyzer.d.ts +27 -0
  232. package/dist/intent-analyzer.d.ts.map +1 -0
  233. package/dist/intent-analyzer.js +140 -0
  234. package/dist/intent-analyzer.js.map +1 -0
  235. package/dist/logging/server-log-manager.d.ts +75 -0
  236. package/dist/logging/server-log-manager.d.ts.map +1 -0
  237. package/dist/logging/server-log-manager.js +185 -0
  238. package/dist/logging/server-log-manager.js.map +1 -0
  239. package/dist/mcp-registry.d.ts +35 -0
  240. package/dist/mcp-registry.d.ts.map +1 -0
  241. package/dist/mcp-registry.js +166 -0
  242. package/dist/mcp-registry.js.map +1 -0
  243. package/dist/middleware/auth.d.ts +5 -0
  244. package/dist/middleware/auth.d.ts.map +1 -0
  245. package/dist/middleware/auth.js +81 -0
  246. package/dist/middleware/auth.js.map +1 -0
  247. package/dist/mock-tool-database.d.ts +41 -0
  248. package/dist/mock-tool-database.d.ts.map +1 -0
  249. package/dist/mock-tool-database.js +461 -0
  250. package/dist/mock-tool-database.js.map +1 -0
  251. package/dist/proxy-server-manager.d.ts +11 -0
  252. package/dist/proxy-server-manager.d.ts.map +1 -0
  253. package/dist/proxy-server-manager.js +144 -0
  254. package/dist/proxy-server-manager.js.map +1 -0
  255. package/dist/router/tool-router.d.ts +61 -0
  256. package/dist/router/tool-router.d.ts.map +1 -0
  257. package/dist/router/tool-router.js +539 -0
  258. package/dist/router/tool-router.js.map +1 -0
  259. package/dist/router/tool-router.test.d.ts +2 -0
  260. package/dist/router/tool-router.test.d.ts.map +1 -0
  261. package/dist/router/tool-router.test.js +113 -0
  262. package/dist/router/tool-router.test.js.map +1 -0
  263. package/dist/streamable-http-server.d.ts +27 -0
  264. package/dist/streamable-http-server.d.ts.map +1 -0
  265. package/dist/streamable-http-server.js +302 -0
  266. package/dist/streamable-http-server.js.map +1 -0
  267. package/dist/tool-finder.d.ts +21 -0
  268. package/dist/tool-finder.d.ts.map +1 -0
  269. package/dist/tool-finder.js +86 -0
  270. package/dist/tool-finder.js.map +1 -0
  271. package/dist/tool-recommender.d.ts +23 -0
  272. package/dist/tool-recommender.d.ts.map +1 -0
  273. package/dist/tool-recommender.js +200 -0
  274. package/dist/tool-recommender.js.map +1 -0
  275. package/dist/types/index.d.ts +145 -0
  276. package/dist/types/index.d.ts.map +1 -0
  277. package/dist/types/index.js +2 -0
  278. package/dist/types/index.js.map +1 -0
  279. package/dist/utils/server-name-validator.d.ts +47 -0
  280. package/dist/utils/server-name-validator.d.ts.map +1 -0
  281. package/dist/utils/server-name-validator.js +156 -0
  282. package/dist/utils/server-name-validator.js.map +1 -0
  283. package/dist/web/web-server.d.ts +44 -0
  284. package/dist/web/web-server.d.ts.map +1 -0
  285. package/dist/web/web-server.js +500 -0
  286. package/dist/web/web-server.js.map +1 -0
  287. package/package.json +68 -0
  288. package/web/dist/assets/index-DMVhVtNU.css +1 -0
  289. package/web/dist/assets/index-VMXIgcOH.js +92 -0
  290. package/web/dist/assets/index-VMXIgcOH.js.map +1 -0
  291. package/web/dist/index.html +14 -0
@@ -0,0 +1,365 @@
1
+ import axios from 'axios';
2
+ export class ProtocolDetector {
3
+ timeout = 10000; // 10秒超时
4
+ userAgent = 'MCPDog-ProtocolDetector/2.0.1';
5
+ constructor(timeout) {
6
+ if (timeout) {
7
+ this.timeout = timeout;
8
+ }
9
+ }
10
+ /**
11
+ * 自动检测端点支持的最佳协议
12
+ */
13
+ async detectBestProtocol(endpoint, options) {
14
+ console.error(`🔍 Starting protocol detection for: ${endpoint}`);
15
+ // 并行测试所有协议
16
+ const testResults = await Promise.allSettled([
17
+ this.testStreamableHttp(endpoint, options),
18
+ this.testHttpSse(endpoint, options),
19
+ this.testBasicHttp(endpoint, options)
20
+ ]);
21
+ // 分析测试结果
22
+ const results = [];
23
+ for (let i = 0; i < testResults.length; i++) {
24
+ const result = testResults[i];
25
+ if (result.status === 'fulfilled') {
26
+ results.push(result.value);
27
+ }
28
+ else {
29
+ console.error(`Protocol test ${i} failed:`, result.reason);
30
+ }
31
+ }
32
+ // 选择最佳协议
33
+ return this.selectBestProtocol(results, endpoint);
34
+ }
35
+ /**
36
+ * 测试 Streamable HTTP 协议支持
37
+ */
38
+ async testStreamableHttp(endpoint, options) {
39
+ const startTime = Date.now();
40
+ try {
41
+ const response = await axios.post(endpoint, {
42
+ jsonrpc: '2.0',
43
+ id: 'protocol-test',
44
+ method: 'initialize',
45
+ params: {
46
+ protocolVersion: '2025-03-26',
47
+ capabilities: {},
48
+ clientInfo: {
49
+ name: 'mcpdog-detector',
50
+ version: '2.0.1'
51
+ }
52
+ }
53
+ }, {
54
+ timeout: options?.timeout || this.timeout,
55
+ headers: {
56
+ 'Content-Type': 'application/json',
57
+ 'Accept': 'application/json, text/event-stream',
58
+ 'User-Agent': this.userAgent,
59
+ ...(options?.headers || {})
60
+ },
61
+ validateStatus: (status) => status < 500 // 接受 4xx 错误,可能是认证问题
62
+ });
63
+ const responseTime = Date.now() - startTime;
64
+ const features = [];
65
+ // 检查响应特征
66
+ if (response.headers['content-type']?.includes('text/event-stream')) {
67
+ features.push('SSE_STREAMING');
68
+ }
69
+ if (response.headers['content-type']?.includes('application/json')) {
70
+ features.push('JSON_RESPONSE');
71
+ }
72
+ // 检查 MCP 协议版本
73
+ if (response.data && typeof response.data === 'string') {
74
+ // SSE 格式响应
75
+ if (response.data.includes('event: message')) {
76
+ features.push('SSE_EVENTS');
77
+ }
78
+ if (response.data.includes('2025-03-26')) {
79
+ features.push('MCP_2025_03_26');
80
+ }
81
+ }
82
+ else if (response.data && response.data.result) {
83
+ // JSON 格式响应
84
+ if (response.data.result.protocolVersion) {
85
+ features.push(`MCP_${response.data.result.protocolVersion.replace(/-/g, '_')}`);
86
+ }
87
+ }
88
+ return {
89
+ protocol: 'streamable-http',
90
+ supported: response.status === 200,
91
+ responseTime,
92
+ features,
93
+ error: response.status !== 200 ? `HTTP ${response.status}` : undefined
94
+ };
95
+ }
96
+ catch (error) {
97
+ const responseTime = Date.now() - startTime;
98
+ // 分析错误类型
99
+ let errorMessage = error.message;
100
+ if (error.response) {
101
+ errorMessage = `HTTP ${error.response.status}: ${error.response.statusText}`;
102
+ }
103
+ else if (error.code === 'ECONNREFUSED') {
104
+ errorMessage = 'Connection refused - server not running';
105
+ }
106
+ else if (error.code === 'ETIMEDOUT') {
107
+ errorMessage = 'Connection timeout';
108
+ }
109
+ return {
110
+ protocol: 'streamable-http',
111
+ supported: false,
112
+ responseTime,
113
+ features: [],
114
+ error: errorMessage
115
+ };
116
+ }
117
+ }
118
+ /**
119
+ * 测试 HTTP+SSE 协议支持
120
+ */
121
+ async testHttpSse(endpoint, options) {
122
+ const startTime = Date.now();
123
+ try {
124
+ // 尝试访问 SSE 端点
125
+ const sseEndpoint = `${endpoint}/sse`;
126
+ const response = await axios.get(sseEndpoint, {
127
+ timeout: Math.min(options?.timeout || this.timeout, 5000), // SSE 连接用较短超时
128
+ headers: {
129
+ 'Accept': 'text/event-stream',
130
+ 'Cache-Control': 'no-cache',
131
+ 'User-Agent': this.userAgent,
132
+ ...(options?.headers || {})
133
+ },
134
+ validateStatus: (status) => status < 500
135
+ });
136
+ const responseTime = Date.now() - startTime;
137
+ const features = [];
138
+ if (response.headers['content-type']?.includes('text/event-stream')) {
139
+ features.push('SSE_ENDPOINT');
140
+ }
141
+ // 检查是否有端点事件
142
+ if (response.data && typeof response.data === 'string') {
143
+ if (response.data.includes('event: endpoint')) {
144
+ features.push('DYNAMIC_ENDPOINTS');
145
+ }
146
+ if (response.data.includes('sessionId')) {
147
+ features.push('SESSION_SUPPORT');
148
+ }
149
+ }
150
+ // 尝试 POST 端点
151
+ try {
152
+ const postResponse = await axios.post(`${endpoint}/mcp`, {
153
+ jsonrpc: '2.0',
154
+ id: 'test',
155
+ method: 'initialize',
156
+ params: { protocolVersion: '2024-11-05' }
157
+ }, {
158
+ timeout: 3000,
159
+ headers: {
160
+ 'Content-Type': 'application/json',
161
+ 'User-Agent': this.userAgent
162
+ },
163
+ validateStatus: () => true
164
+ });
165
+ if (postResponse.status < 500) {
166
+ features.push('HTTP_POST_ENDPOINT');
167
+ }
168
+ }
169
+ catch {
170
+ // POST 端点测试失败,但不影响 SSE 检测
171
+ }
172
+ return {
173
+ protocol: 'http-sse',
174
+ supported: response.status === 200 && features.includes('SSE_ENDPOINT'),
175
+ responseTime,
176
+ features,
177
+ error: response.status !== 200 ? `HTTP ${response.status}` : undefined
178
+ };
179
+ }
180
+ catch (error) {
181
+ const responseTime = Date.now() - startTime;
182
+ return {
183
+ protocol: 'http-sse',
184
+ supported: false,
185
+ responseTime,
186
+ features: [],
187
+ error: error.response ? `HTTP ${error.response.status}` : error.message
188
+ };
189
+ }
190
+ }
191
+ /**
192
+ * 测试基础 HTTP 支持(作为后备)
193
+ */
194
+ async testBasicHttp(endpoint, options) {
195
+ const startTime = Date.now();
196
+ try {
197
+ const response = await axios.get(endpoint, {
198
+ timeout: options?.timeout || this.timeout,
199
+ headers: {
200
+ 'User-Agent': this.userAgent,
201
+ ...(options?.headers || {})
202
+ },
203
+ validateStatus: () => true
204
+ });
205
+ const responseTime = Date.now() - startTime;
206
+ const features = [];
207
+ // 检查 HTTP 特征
208
+ if (response.headers['content-type']?.includes('application/json')) {
209
+ features.push('JSON_SUPPORT');
210
+ }
211
+ if (response.headers['server']) {
212
+ features.push(`SERVER_${response.headers['server'].replace(/\s+/g, '_')}`);
213
+ }
214
+ // 检查是否返回 MCP 相关信息
215
+ if (response.data && typeof response.data === 'object') {
216
+ if (response.data.jsonrpc) {
217
+ features.push('JSONRPC_SUPPORT');
218
+ }
219
+ if (response.data.result || response.data.error) {
220
+ features.push('MCP_RESPONSE_FORMAT');
221
+ }
222
+ }
223
+ return {
224
+ protocol: 'basic-http',
225
+ supported: response.status < 400,
226
+ responseTime,
227
+ features,
228
+ error: response.status >= 400 ? `HTTP ${response.status}` : undefined
229
+ };
230
+ }
231
+ catch (error) {
232
+ const responseTime = Date.now() - startTime;
233
+ return {
234
+ protocol: 'basic-http',
235
+ supported: false,
236
+ responseTime,
237
+ features: [],
238
+ error: error.response ? `HTTP ${error.response.status}` : error.message
239
+ };
240
+ }
241
+ }
242
+ /**
243
+ * 选择最佳协议
244
+ */
245
+ selectBestProtocol(results, endpoint) {
246
+ // 协议优先级权重
247
+ const protocolWeights = {
248
+ 'streamable-http': 100, // 最新协议,最高优先级
249
+ 'http-sse': 70, // 传统协议,中等优先级
250
+ 'basic-http': 30 // 基础协议,最低优先级
251
+ };
252
+ let bestResult = {
253
+ protocol: 'unknown',
254
+ confidence: 0,
255
+ reason: 'No protocols detected'
256
+ };
257
+ for (const result of results) {
258
+ if (!result.supported) {
259
+ continue;
260
+ }
261
+ // 计算置信度
262
+ let confidence = protocolWeights[result.protocol] || 0;
263
+ // 根据响应时间调整 (响应时间越快,置信度越高)
264
+ if (result.responseTime < 1000) {
265
+ confidence += 10;
266
+ }
267
+ else if (result.responseTime > 5000) {
268
+ confidence -= 10;
269
+ }
270
+ // 根据功能特征调整
271
+ confidence += result.features.length * 5;
272
+ // 特殊加分
273
+ if (result.features.includes('MCP_2025_03_26')) {
274
+ confidence += 20; // 最新协议版本
275
+ }
276
+ if (result.features.includes('SSE_STREAMING')) {
277
+ confidence += 15; // 流式支持
278
+ }
279
+ if (result.features.includes('SESSION_SUPPORT')) {
280
+ confidence += 10; // 会话支持
281
+ }
282
+ // 更新最佳结果
283
+ if (confidence > bestResult.confidence) {
284
+ bestResult = {
285
+ protocol: result.protocol,
286
+ confidence: Math.min(confidence, 100),
287
+ reason: this.generateReasonText(result),
288
+ endpoint,
289
+ features: result.features,
290
+ error: result.error
291
+ };
292
+ }
293
+ }
294
+ console.error(`🎯 Best protocol for ${endpoint}: ${bestResult.protocol} (confidence: ${bestResult.confidence}%)`);
295
+ console.error(`📋 Reason: ${bestResult.reason}`);
296
+ return bestResult;
297
+ }
298
+ /**
299
+ * 生成检测原因说明
300
+ */
301
+ generateReasonText(result) {
302
+ const reasons = [];
303
+ if (result.protocol === 'streamable-http') {
304
+ reasons.push('Latest MCP protocol (2025-03-26)');
305
+ if (result.features.includes('SSE_STREAMING')) {
306
+ reasons.push('Supports streaming responses');
307
+ }
308
+ if (result.features.includes('JSON_RESPONSE')) {
309
+ reasons.push('JSON response format');
310
+ }
311
+ }
312
+ else if (result.protocol === 'http-sse') {
313
+ reasons.push('Traditional MCP HTTP+SSE protocol');
314
+ if (result.features.includes('DYNAMIC_ENDPOINTS')) {
315
+ reasons.push('Dynamic endpoint discovery');
316
+ }
317
+ if (result.features.includes('SESSION_SUPPORT')) {
318
+ reasons.push('Session management');
319
+ }
320
+ }
321
+ else {
322
+ reasons.push('Basic HTTP endpoint');
323
+ }
324
+ if (result.responseTime < 1000) {
325
+ reasons.push(`Fast response (${result.responseTime}ms)`);
326
+ }
327
+ return reasons.join(', ');
328
+ }
329
+ /**
330
+ * 为 stdio 协议生成配置建议
331
+ */
332
+ generateStdioSuggestion(command) {
333
+ return {
334
+ protocol: 'stdio',
335
+ confidence: 95,
336
+ reason: 'Command-based MCP server',
337
+ features: ['PROCESS_COMMUNICATION', 'DIRECT_EXECUTION']
338
+ };
339
+ }
340
+ /**
341
+ * 批量检测多个端点
342
+ */
343
+ async detectMultipleEndpoints(endpoints) {
344
+ const results = new Map();
345
+ console.error(`🔍 Batch protocol detection for ${endpoints.length} endpoints`);
346
+ const detectionPromises = endpoints.map(async (endpoint) => {
347
+ try {
348
+ const result = await this.detectBestProtocol(endpoint);
349
+ results.set(endpoint, result);
350
+ }
351
+ catch (error) {
352
+ results.set(endpoint, {
353
+ protocol: 'unknown',
354
+ confidence: 0,
355
+ reason: `Detection failed: ${error.message}`,
356
+ error: error.message
357
+ });
358
+ }
359
+ });
360
+ await Promise.allSettled(detectionPromises);
361
+ console.error(`✅ Batch detection completed: ${results.size} results`);
362
+ return results;
363
+ }
364
+ }
365
+ //# sourceMappingURL=protocol-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol-detector.js","sourceRoot":"","sources":["../../src/core/protocol-detector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * MCPDog Daemon Client(HTTP 版)
3
+ * daemon IPC 已与 Web 端口合并(doc/20260907-设计文档-daemon-IPC与Web端口合并.md):
4
+ * 探活走 GET /api/status,MCP 转发走 POST /api/mcp,clientId 由 X-MCPDog-Client 头携带。
5
+ */
6
+ import { EventEmitter } from 'events';
7
+ export interface DaemonClientConfig {
8
+ baseUrl: string;
9
+ clientType: 'stdio' | 'web' | 'cli';
10
+ token?: string;
11
+ silent?: boolean;
12
+ requestTimeoutMs?: number;
13
+ connectAttempts?: number;
14
+ connectIntervalMs?: number;
15
+ retryDelayMs?: number;
16
+ }
17
+ export declare class DaemonClient extends EventEmitter {
18
+ private config;
19
+ private isConnected;
20
+ private readonly clientId;
21
+ constructor(config: DaemonClientConfig);
22
+ getClientId(): string;
23
+ private buildHeaders;
24
+ private probeOnce;
25
+ connect(): Promise<void>;
26
+ disconnect(): void;
27
+ private postJson;
28
+ sendMCPRequest(request: any): Promise<any>;
29
+ getStatus(): Promise<any>;
30
+ getTools(): Promise<any>;
31
+ reloadConfig(): Promise<any>;
32
+ get connected(): boolean;
33
+ }
34
+ //# sourceMappingURL=daemon-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon-client.d.ts","sourceRoot":"","sources":["../../src/daemon/daemon-client.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAGtC,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,OAAO,GAAG,KAAK,GAAG,KAAK,CAAC;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,qBAAa,YAAa,SAAQ,YAAY;IAC5C,OAAO,CAAC,MAAM,CACoE;IAClF,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;gBAEtB,MAAM,EAAE,kBAAkB;IAmBtC,WAAW,IAAI,MAAM;IAIrB,OAAO,CAAC,YAAY;YAYN,SAAS;IAajB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAkB9B,UAAU,IAAI,IAAI;YAIJ,QAAQ;IAehB,cAAc,CAAC,OAAO,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;IAY1C,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC;IAWzB,QAAQ,IAAI,OAAO,CAAC,GAAG,CAAC;IAWxB,YAAY,IAAI,OAAO,CAAC,GAAG,CAAC;IAIlC,IAAI,SAAS,IAAI,OAAO,CAEvB;CACF"}
@@ -0,0 +1,130 @@
1
+ /**
2
+ * MCPDog Daemon Client(HTTP 版)
3
+ * daemon IPC 已与 Web 端口合并(doc/20260907-设计文档-daemon-IPC与Web端口合并.md):
4
+ * 探活走 GET /api/status,MCP 转发走 POST /api/mcp,clientId 由 X-MCPDog-Client 头携带。
5
+ */
6
+ import { EventEmitter } from 'events';
7
+ import { randomUUID } from 'crypto';
8
+ export class DaemonClient extends EventEmitter {
9
+ config;
10
+ isConnected = false;
11
+ clientId;
12
+ constructor(config) {
13
+ super();
14
+ this.config = {
15
+ requestTimeoutMs: 120000,
16
+ connectAttempts: 10,
17
+ connectIntervalMs: 1000,
18
+ retryDelayMs: 500,
19
+ ...config
20
+ };
21
+ // token 缺省回退到环境变量:daemon 一旦设置 MCPDOG_AUTH_TOKEN,auth 中间件对所有 /api/*(含
22
+ // /api/mcp、/api/status)强制 Bearer,且无 loopback 豁免(src/middleware/auth.ts:43-101)。本机
23
+ // proxy/CLI 与 daemon 共享 env(auto-start 经 spawn 继承 process.env),缺省带上可避免
24
+ // "设了 token 后本机 proxy/CLI 全部 401" 的合并回归(旧 IPC 9999 无鉴权)。
25
+ if (!this.config.token && process.env.MCPDOG_AUTH_TOKEN) {
26
+ this.config.token = process.env.MCPDOG_AUTH_TOKEN;
27
+ }
28
+ this.clientId = `client_${randomUUID().slice(0, 8)}`;
29
+ }
30
+ getClientId() {
31
+ return this.clientId;
32
+ }
33
+ buildHeaders() {
34
+ const headers = {
35
+ 'Content-Type': 'application/json',
36
+ 'X-MCPDog-Client': this.clientId
37
+ };
38
+ if (this.config.token) {
39
+ headers['Authorization'] = `Bearer ${this.config.token}`;
40
+ }
41
+ return headers;
42
+ }
43
+ // 探活一次(不重试)
44
+ async probeOnce() {
45
+ try {
46
+ const res = await fetch(`${this.config.baseUrl}/api/status`, {
47
+ headers: this.buildHeaders(),
48
+ signal: AbortSignal.timeout(5000)
49
+ });
50
+ return res.ok;
51
+ }
52
+ catch {
53
+ return false;
54
+ }
55
+ }
56
+ // Public API —— 探活重试直到 daemon 就绪(替代原 TCP welcome 语义)
57
+ async connect() {
58
+ for (let i = 0; i < this.config.connectAttempts; i++) {
59
+ if (await this.probeOnce()) {
60
+ this.isConnected = true;
61
+ if (!this.config.silent) {
62
+ console.log(`[DAEMON-CLIENT] Daemon ready at ${this.config.baseUrl} (client ${this.clientId})`);
63
+ }
64
+ this.emit('connected');
65
+ this.emit('ready');
66
+ return;
67
+ }
68
+ if (i < this.config.connectAttempts - 1) {
69
+ await new Promise((r) => setTimeout(r, this.config.connectIntervalMs));
70
+ }
71
+ }
72
+ throw new Error(`Daemon not reachable at ${this.config.baseUrl} (tried ${this.config.connectAttempts} times)`);
73
+ }
74
+ disconnect() {
75
+ this.isConnected = false;
76
+ }
77
+ async postJson(path, body) {
78
+ const res = await fetch(`${this.config.baseUrl}${path}`, {
79
+ method: 'POST',
80
+ headers: this.buildHeaders(),
81
+ body: JSON.stringify(body),
82
+ signal: AbortSignal.timeout(this.config.requestTimeoutMs)
83
+ });
84
+ if (!res.ok) {
85
+ throw new Error(`daemon HTTP ${res.status} on ${path}`);
86
+ }
87
+ return res.json();
88
+ }
89
+ // MCP protocol forwarding —— 失败先探活,daemon 可达则重试一次
90
+ // (替代原 socket reconnect 的 daemon 重启自愈语义)
91
+ async sendMCPRequest(request) {
92
+ try {
93
+ return await this.postJson('/api/mcp', request);
94
+ }
95
+ catch (error) {
96
+ await new Promise((r) => setTimeout(r, this.config.retryDelayMs));
97
+ if (await this.probeOnce()) {
98
+ return await this.postJson('/api/mcp', request);
99
+ }
100
+ throw error;
101
+ }
102
+ }
103
+ async getStatus() {
104
+ const res = await fetch(`${this.config.baseUrl}/api/status`, {
105
+ headers: this.buildHeaders(),
106
+ signal: AbortSignal.timeout(this.config.requestTimeoutMs)
107
+ });
108
+ if (!res.ok) {
109
+ throw new Error(`daemon HTTP ${res.status} on /api/status`);
110
+ }
111
+ return res.json();
112
+ }
113
+ async getTools() {
114
+ const res = await fetch(`${this.config.baseUrl}/api/tools`, {
115
+ headers: this.buildHeaders(),
116
+ signal: AbortSignal.timeout(this.config.requestTimeoutMs)
117
+ });
118
+ if (!res.ok) {
119
+ throw new Error(`daemon HTTP ${res.status} on /api/tools`);
120
+ }
121
+ return res.json();
122
+ }
123
+ async reloadConfig() {
124
+ return this.postJson('/api/daemon/reload', {});
125
+ }
126
+ get connected() {
127
+ return this.isConnected;
128
+ }
129
+ }
130
+ //# sourceMappingURL=daemon-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon-client.js","sourceRoot":"","sources":["../../src/daemon/daemon-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=daemon-client.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon-client.test.d.ts","sourceRoot":"","sources":["../../src/daemon/daemon-client.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,77 @@
1
+ import { describe, it, expect, beforeAll, afterAll } from 'vitest';
2
+ import { createServer } from 'http';
3
+ import { DaemonClient } from './daemon-client';
4
+ describe('DaemonClient (HTTP)', () => {
5
+ let server;
6
+ let baseUrl;
7
+ let mcpFailFirst = false;
8
+ beforeAll(async () => {
9
+ server = createServer((req, res) => {
10
+ const chunks = [];
11
+ req.on('data', (c) => chunks.push(c));
12
+ req.on('end', () => {
13
+ const body = Buffer.concat(chunks).toString();
14
+ if (req.method === 'GET' && req.url === '/api/status') {
15
+ res.writeHead(200, { 'Content-Type': 'application/json' });
16
+ res.end(JSON.stringify({ daemon: { isRunning: true } }));
17
+ }
18
+ else if (req.method === 'POST' && req.url === '/api/mcp') {
19
+ if (mcpFailFirst) {
20
+ mcpFailFirst = false; // 模拟 daemon 重启后首次请求失败
21
+ res.writeHead(503);
22
+ res.end('{}');
23
+ return;
24
+ }
25
+ const request = JSON.parse(body);
26
+ res.writeHead(200, { 'Content-Type': 'application/json' });
27
+ res.end(JSON.stringify({
28
+ jsonrpc: '2.0',
29
+ id: request.id,
30
+ result: { clientId: req.headers['x-mcpdog-client'] }
31
+ }));
32
+ }
33
+ else {
34
+ res.writeHead(404);
35
+ res.end('{}');
36
+ }
37
+ });
38
+ });
39
+ await new Promise((r) => server.listen(0, 'localhost', r));
40
+ baseUrl = `http://localhost:${server.address().port}`;
41
+ });
42
+ afterAll(() => new Promise((r) => server.close(() => r())));
43
+ it('connect 探活成功后 resolve 并置 connected', async () => {
44
+ const client = new DaemonClient({ baseUrl, clientType: 'cli', silent: true });
45
+ await expect(client.connect()).resolves.toBeUndefined();
46
+ expect(client.connected).toBe(true);
47
+ client.disconnect();
48
+ });
49
+ it('sendMCPRequest 转发 JSON-RPC 并携带 X-MCPDog-Client 头', async () => {
50
+ const client = new DaemonClient({ baseUrl, clientType: 'cli', silent: true });
51
+ const response = await client.sendMCPRequest({ jsonrpc: '2.0', id: 1, method: 'tools/list', params: {} });
52
+ expect(response.id).toBe(1);
53
+ expect(String(response.result.clientId)).toMatch(/^client_/);
54
+ });
55
+ it('daemon 重启场景:请求失败后探活可达则重试一次成功', async () => {
56
+ mcpFailFirst = true;
57
+ const client = new DaemonClient({ baseUrl, clientType: 'cli', silent: true, retryDelayMs: 10 });
58
+ const response = await client.sendMCPRequest({ jsonrpc: '2.0', id: 2, method: 'ping' });
59
+ expect(response.id).toBe(2);
60
+ });
61
+ it('getStatus 返回 /api/status 的 JSON', async () => {
62
+ const client = new DaemonClient({ baseUrl, clientType: 'cli', silent: true });
63
+ const status = await client.getStatus();
64
+ expect(status.daemon.isRunning).toBe(true);
65
+ });
66
+ it('服务不可达时 connect 重试耗尽后 reject', async () => {
67
+ const client = new DaemonClient({
68
+ baseUrl: 'http://localhost:1', // 无人监听端口,连接立即拒绝
69
+ clientType: 'cli',
70
+ silent: true,
71
+ connectAttempts: 2,
72
+ connectIntervalMs: 10
73
+ });
74
+ await expect(client.connect()).rejects.toThrow(/not reachable/);
75
+ });
76
+ });
77
+ //# sourceMappingURL=daemon-client.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon-client.test.js","sourceRoot":"","sources":["../../src/daemon/daemon-client.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export interface DaemonInfo {
2
+ pid: number;
3
+ version: string | null;
4
+ }
5
+ export declare function readDaemonInfo(pidFile: string): Promise<DaemonInfo | null>;
6
+ export declare function isProcessAlive(pid: number): boolean;
7
+ //# sourceMappingURL=daemon-info.d.ts.map