@coffeerunhobby/mcp-ha-connect 0.5.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 (294) hide show
  1. package/.dockerignore +8 -0
  2. package/.env.example +149 -0
  3. package/.gitattributes +30 -0
  4. package/Dockerfile +33 -0
  5. package/LICENSE +21 -0
  6. package/README.md +394 -0
  7. package/dist/config.d.ts +33 -0
  8. package/dist/config.d.ts.map +1 -0
  9. package/dist/config.js +183 -0
  10. package/dist/config.js.map +1 -0
  11. package/dist/haClient/automations.d.ts +67 -0
  12. package/dist/haClient/automations.d.ts.map +1 -0
  13. package/dist/haClient/automations.js +181 -0
  14. package/dist/haClient/automations.js.map +1 -0
  15. package/dist/haClient/config.d.ts +28 -0
  16. package/dist/haClient/config.d.ts.map +1 -0
  17. package/dist/haClient/config.js +38 -0
  18. package/dist/haClient/config.js.map +1 -0
  19. package/dist/haClient/devices.d.ts +219 -0
  20. package/dist/haClient/devices.d.ts.map +1 -0
  21. package/dist/haClient/devices.js +506 -0
  22. package/dist/haClient/devices.js.map +1 -0
  23. package/dist/haClient/entities.d.ts +35 -0
  24. package/dist/haClient/entities.d.ts.map +1 -0
  25. package/dist/haClient/entities.js +97 -0
  26. package/dist/haClient/entities.js.map +1 -0
  27. package/dist/haClient/events.d.ts +138 -0
  28. package/dist/haClient/events.d.ts.map +1 -0
  29. package/dist/haClient/events.js +344 -0
  30. package/dist/haClient/events.js.map +1 -0
  31. package/dist/haClient/history.d.ts +26 -0
  32. package/dist/haClient/history.d.ts.map +1 -0
  33. package/dist/haClient/history.js +54 -0
  34. package/dist/haClient/history.js.map +1 -0
  35. package/dist/haClient/index.d.ts +153 -0
  36. package/dist/haClient/index.d.ts.map +1 -0
  37. package/dist/haClient/index.js +223 -0
  38. package/dist/haClient/index.js.map +1 -0
  39. package/dist/haClient/request.d.ts +34 -0
  40. package/dist/haClient/request.d.ts.map +1 -0
  41. package/dist/haClient/request.js +93 -0
  42. package/dist/haClient/request.js.map +1 -0
  43. package/dist/haClient/services.d.ts +22 -0
  44. package/dist/haClient/services.d.ts.map +1 -0
  45. package/dist/haClient/services.js +39 -0
  46. package/dist/haClient/services.js.map +1 -0
  47. package/dist/haClient/states.d.ts +26 -0
  48. package/dist/haClient/states.d.ts.map +1 -0
  49. package/dist/haClient/states.js +53 -0
  50. package/dist/haClient/states.js.map +1 -0
  51. package/dist/haClient/updates.d.ts +22 -0
  52. package/dist/haClient/updates.d.ts.map +1 -0
  53. package/dist/haClient/updates.js +48 -0
  54. package/dist/haClient/updates.js.map +1 -0
  55. package/dist/haClient.d.ts +97 -0
  56. package/dist/haClient.d.ts.map +1 -0
  57. package/dist/haClient.js +344 -0
  58. package/dist/haClient.js.map +1 -0
  59. package/dist/index.d.ts +8 -0
  60. package/dist/index.d.ts.map +1 -0
  61. package/dist/index.js +92 -0
  62. package/dist/index.js.map +1 -0
  63. package/dist/localAI/index.d.ts +37 -0
  64. package/dist/localAI/index.d.ts.map +1 -0
  65. package/dist/localAI/index.js +73 -0
  66. package/dist/localAI/index.js.map +1 -0
  67. package/dist/localAI/prompts.d.ts +20 -0
  68. package/dist/localAI/prompts.d.ts.map +1 -0
  69. package/dist/localAI/prompts.js +48 -0
  70. package/dist/localAI/prompts.js.map +1 -0
  71. package/dist/localAI/providers/base.d.ts +51 -0
  72. package/dist/localAI/providers/base.d.ts.map +1 -0
  73. package/dist/localAI/providers/base.js +80 -0
  74. package/dist/localAI/providers/base.js.map +1 -0
  75. package/dist/localAI/providers/ollama.d.ts +22 -0
  76. package/dist/localAI/providers/ollama.d.ts.map +1 -0
  77. package/dist/localAI/providers/ollama.js +63 -0
  78. package/dist/localAI/providers/ollama.js.map +1 -0
  79. package/dist/localAI/providers/openai.d.ts +23 -0
  80. package/dist/localAI/providers/openai.d.ts.map +1 -0
  81. package/dist/localAI/providers/openai.js +63 -0
  82. package/dist/localAI/providers/openai.js.map +1 -0
  83. package/dist/localAI/types.d.ts +61 -0
  84. package/dist/localAI/types.d.ts.map +1 -0
  85. package/dist/localAI/types.js +6 -0
  86. package/dist/localAI/types.js.map +1 -0
  87. package/dist/ollamaClient.d.ts +37 -0
  88. package/dist/ollamaClient.d.ts.map +1 -0
  89. package/dist/ollamaClient.js +110 -0
  90. package/dist/ollamaClient.js.map +1 -0
  91. package/dist/resources/index.d.ts +11 -0
  92. package/dist/resources/index.d.ts.map +1 -0
  93. package/dist/resources/index.js +238 -0
  94. package/dist/resources/index.js.map +1 -0
  95. package/dist/server/common.d.ts +9 -0
  96. package/dist/server/common.d.ts.map +1 -0
  97. package/dist/server/common.js +27 -0
  98. package/dist/server/common.js.map +1 -0
  99. package/dist/server/eventSubscription.d.ts +53 -0
  100. package/dist/server/eventSubscription.d.ts.map +1 -0
  101. package/dist/server/eventSubscription.js +257 -0
  102. package/dist/server/eventSubscription.js.map +1 -0
  103. package/dist/server/http.d.ts +12 -0
  104. package/dist/server/http.d.ts.map +1 -0
  105. package/dist/server/http.js +491 -0
  106. package/dist/server/http.js.map +1 -0
  107. package/dist/server/rateLimiter.d.ts +70 -0
  108. package/dist/server/rateLimiter.d.ts.map +1 -0
  109. package/dist/server/rateLimiter.js +156 -0
  110. package/dist/server/rateLimiter.js.map +1 -0
  111. package/dist/server/sse.d.ts +32 -0
  112. package/dist/server/sse.d.ts.map +1 -0
  113. package/dist/server/sse.js +76 -0
  114. package/dist/server/sse.js.map +1 -0
  115. package/dist/server/stdio.d.ts +8 -0
  116. package/dist/server/stdio.d.ts.map +1 -0
  117. package/dist/server/stdio.js +16 -0
  118. package/dist/server/stdio.js.map +1 -0
  119. package/dist/server/stream.d.ts +26 -0
  120. package/dist/server/stream.d.ts.map +1 -0
  121. package/dist/server/stream.js +81 -0
  122. package/dist/server/stream.js.map +1 -0
  123. package/dist/server.d.ts +8 -0
  124. package/dist/server.d.ts.map +1 -0
  125. package/dist/server.js +30 -0
  126. package/dist/server.js.map +1 -0
  127. package/dist/tools/callService.d.ts +8 -0
  128. package/dist/tools/callService.d.ts.map +1 -0
  129. package/dist/tools/callService.js +100 -0
  130. package/dist/tools/callService.js.map +1 -0
  131. package/dist/tools/getClient.d.ts +8 -0
  132. package/dist/tools/getClient.d.ts.map +1 -0
  133. package/dist/tools/getClient.js +94 -0
  134. package/dist/tools/getClient.js.map +1 -0
  135. package/dist/tools/getDevice.d.ts +8 -0
  136. package/dist/tools/getDevice.d.ts.map +1 -0
  137. package/dist/tools/getDevice.js +94 -0
  138. package/dist/tools/getDevice.js.map +1 -0
  139. package/dist/tools/getEntitiesByDomain.d.ts +8 -0
  140. package/dist/tools/getEntitiesByDomain.d.ts.map +1 -0
  141. package/dist/tools/getEntitiesByDomain.js +80 -0
  142. package/dist/tools/getEntitiesByDomain.js.map +1 -0
  143. package/dist/tools/getState.d.ts +8 -0
  144. package/dist/tools/getState.d.ts.map +1 -0
  145. package/dist/tools/getState.js +90 -0
  146. package/dist/tools/getState.js.map +1 -0
  147. package/dist/tools/getStates.d.ts +8 -0
  148. package/dist/tools/getStates.d.ts.map +1 -0
  149. package/dist/tools/getStates.js +70 -0
  150. package/dist/tools/getStates.js.map +1 -0
  151. package/dist/tools/index.d.ts +9 -0
  152. package/dist/tools/index.d.ts.map +1 -0
  153. package/dist/tools/index.js +9 -0
  154. package/dist/tools/index.js.map +1 -0
  155. package/dist/tools/listClients.d.ts +8 -0
  156. package/dist/tools/listClients.d.ts.map +1 -0
  157. package/dist/tools/listClients.js +73 -0
  158. package/dist/tools/listClients.js.map +1 -0
  159. package/dist/tools/listDevices.d.ts +8 -0
  160. package/dist/tools/listDevices.d.ts.map +1 -0
  161. package/dist/tools/listDevices.js +73 -0
  162. package/dist/tools/listDevices.js.map +1 -0
  163. package/dist/tools/listSites.d.ts +8 -0
  164. package/dist/tools/listSites.d.ts.map +1 -0
  165. package/dist/tools/listSites.js +67 -0
  166. package/dist/tools/listSites.js.map +1 -0
  167. package/dist/tools/registry.d.ts +9 -0
  168. package/dist/tools/registry.d.ts.map +1 -0
  169. package/dist/tools/registry.js +1382 -0
  170. package/dist/tools/registry.js.map +1 -0
  171. package/dist/tools/searchDevices.d.ts +8 -0
  172. package/dist/tools/searchDevices.d.ts.map +1 -0
  173. package/dist/tools/searchDevices.js +84 -0
  174. package/dist/tools/searchDevices.js.map +1 -0
  175. package/dist/tools/searchEntities.d.ts +8 -0
  176. package/dist/tools/searchEntities.d.ts.map +1 -0
  177. package/dist/tools/searchEntities.js +80 -0
  178. package/dist/tools/searchEntities.js.map +1 -0
  179. package/dist/types/entity.d.ts +98 -0
  180. package/dist/types/entity.d.ts.map +1 -0
  181. package/dist/types/entity.js +2 -0
  182. package/dist/types/entity.js.map +1 -0
  183. package/dist/types/errors.d.ts +16 -0
  184. package/dist/types/errors.d.ts.map +1 -0
  185. package/dist/types/errors.js +32 -0
  186. package/dist/types/errors.js.map +1 -0
  187. package/dist/types/haConfig.d.ts +8 -0
  188. package/dist/types/haConfig.d.ts.map +1 -0
  189. package/dist/types/haConfig.js +2 -0
  190. package/dist/types/haConfig.js.map +1 -0
  191. package/dist/types/index.d.ts +6 -0
  192. package/dist/types/index.d.ts.map +1 -0
  193. package/dist/types/index.js +2 -0
  194. package/dist/types/index.js.map +1 -0
  195. package/dist/types/request.d.ts +7 -0
  196. package/dist/types/request.d.ts.map +1 -0
  197. package/dist/types/request.js +2 -0
  198. package/dist/types/request.js.map +1 -0
  199. package/dist/types/serviceCall.d.ts +18 -0
  200. package/dist/types/serviceCall.d.ts.map +1 -0
  201. package/dist/types/serviceCall.js +2 -0
  202. package/dist/types/serviceCall.js.map +1 -0
  203. package/dist/types.d.ts +2 -0
  204. package/dist/types.d.ts.map +1 -0
  205. package/dist/types.js +3 -0
  206. package/dist/types.js.map +1 -0
  207. package/dist/utils/config-validations.d.ts +12 -0
  208. package/dist/utils/config-validations.d.ts.map +1 -0
  209. package/dist/utils/config-validations.js +43 -0
  210. package/dist/utils/config-validations.js.map +1 -0
  211. package/dist/utils/logger.d.ts +24 -0
  212. package/dist/utils/logger.d.ts.map +1 -0
  213. package/dist/utils/logger.js +94 -0
  214. package/dist/utils/logger.js.map +1 -0
  215. package/dist/wrapper.d.ts +8 -0
  216. package/dist/wrapper.d.ts.map +1 -0
  217. package/dist/wrapper.js +301 -0
  218. package/dist/wrapper.js.map +1 -0
  219. package/docker-compose.yml +17 -0
  220. package/docs/CHANGELOG.md +86 -0
  221. package/docs/LOCAL_CLIENT.md +268 -0
  222. package/docs/SSE_API.md +341 -0
  223. package/eslint.config.js +33 -0
  224. package/n8n/ai-agent-safety-monitor.json +355 -0
  225. package/openapi.json +166 -0
  226. package/package.json +51 -0
  227. package/src/config.ts +260 -0
  228. package/src/haClient/automations.ts +217 -0
  229. package/src/haClient/config.ts +41 -0
  230. package/src/haClient/devices.ts +653 -0
  231. package/src/haClient/entities.ts +128 -0
  232. package/src/haClient/events.ts +456 -0
  233. package/src/haClient/history.ts +68 -0
  234. package/src/haClient/index.ts +287 -0
  235. package/src/haClient/request.ts +127 -0
  236. package/src/haClient/services.ts +45 -0
  237. package/src/haClient/states.ts +60 -0
  238. package/src/haClient/updates.ts +58 -0
  239. package/src/index.ts +99 -0
  240. package/src/localAI/index.ts +88 -0
  241. package/src/localAI/prompts.ts +50 -0
  242. package/src/localAI/providers/base.ts +120 -0
  243. package/src/localAI/providers/ollama.ts +78 -0
  244. package/src/localAI/providers/openai.ts +86 -0
  245. package/src/localAI/types.ts +67 -0
  246. package/src/resources/index.ts +266 -0
  247. package/src/server/common.ts +38 -0
  248. package/src/server/eventSubscription.ts +318 -0
  249. package/src/server/http.ts +546 -0
  250. package/src/server/rateLimiter.ts +195 -0
  251. package/src/server/sse.ts +120 -0
  252. package/src/server/stdio.ts +22 -0
  253. package/src/server/stream.ts +113 -0
  254. package/src/tools/callService.ts +114 -0
  255. package/src/tools/getEntitiesByDomain.ts +92 -0
  256. package/src/tools/getState.ts +103 -0
  257. package/src/tools/getStates.ts +80 -0
  258. package/src/tools/index.ts +9 -0
  259. package/src/tools/registry.ts +1521 -0
  260. package/src/tools/searchEntities.ts +92 -0
  261. package/src/types/entity.ts +110 -0
  262. package/src/types/errors.ts +33 -0
  263. package/src/types/haConfig.ts +7 -0
  264. package/src/types/index.ts +5 -0
  265. package/src/types/request.ts +6 -0
  266. package/src/types/serviceCall.ts +18 -0
  267. package/src/types.ts +2 -0
  268. package/src/utils/config-validations.ts +46 -0
  269. package/src/utils/logger.ts +114 -0
  270. package/src/wrapper.ts +340 -0
  271. package/tests/config.test.ts +332 -0
  272. package/tests/haClient/automations.test.ts +133 -0
  273. package/tests/haClient/config.test.ts +96 -0
  274. package/tests/haClient/entities.test.ts +188 -0
  275. package/tests/haClient/history.test.ts +170 -0
  276. package/tests/haClient/index.test.ts +221 -0
  277. package/tests/haClient/request.test.ts +217 -0
  278. package/tests/haClient/services.test.ts +120 -0
  279. package/tests/haClient/states.test.ts +119 -0
  280. package/tests/haClient/updates.test.ts +193 -0
  281. package/tests/index.test.ts +164 -0
  282. package/tests/localAI/index.test.ts +168 -0
  283. package/tests/localAI/ollama.test.ts +187 -0
  284. package/tests/localAI/openai.test.ts +257 -0
  285. package/tests/server/common.test.ts +64 -0
  286. package/tests/server/http.test.ts +326 -0
  287. package/tests/server/sse.test.ts +240 -0
  288. package/tests/server/stdio.test.ts +102 -0
  289. package/tests/server/stream.test.ts +287 -0
  290. package/tests/tools/registry.test.ts +355 -0
  291. package/tests/utils/config-validations.test.ts +289 -0
  292. package/tests/utils/logger.test.ts +327 -0
  293. package/tsconfig.json +25 -0
  294. package/vitest.config.ts +26 -0
@@ -0,0 +1,156 @@
1
+ /**
2
+ * Rate Limiter Middleware
3
+ * Simple token bucket rate limiter for HTTP endpoints
4
+ */
5
+ import { logger } from '../utils/logger.js';
6
+ /**
7
+ * Rate Limiter class
8
+ */
9
+ export class RateLimiter {
10
+ windowMs;
11
+ maxRequests;
12
+ skipPaths;
13
+ keyGenerator;
14
+ entries = new Map();
15
+ cleanupInterval = null;
16
+ constructor(config = {}) {
17
+ this.windowMs = config.windowMs ?? 60000; // 1 minute default
18
+ this.maxRequests = config.maxRequests ?? 100; // 100 requests per minute
19
+ this.skipPaths = new Set(config.skipPaths ?? ['/health', '/healthcheck']);
20
+ this.keyGenerator = config.keyGenerator ?? this.defaultKeyGenerator;
21
+ // Start cleanup interval to prevent memory leaks
22
+ this.startCleanup();
23
+ }
24
+ /**
25
+ * Default key generator - uses IP address
26
+ */
27
+ defaultKeyGenerator(req) {
28
+ // Try to get real IP from common proxy headers
29
+ const forwardedFor = req.headers['x-forwarded-for'];
30
+ if (forwardedFor) {
31
+ const ips = Array.isArray(forwardedFor) ? forwardedFor[0] : forwardedFor;
32
+ return ips.split(',')[0].trim();
33
+ }
34
+ const realIp = req.headers['x-real-ip'];
35
+ if (realIp) {
36
+ return Array.isArray(realIp) ? realIp[0] : realIp;
37
+ }
38
+ // Fall back to socket remote address
39
+ return req.socket.remoteAddress ?? 'unknown';
40
+ }
41
+ /**
42
+ * Start periodic cleanup of expired entries
43
+ */
44
+ startCleanup() {
45
+ // Cleanup every window period
46
+ this.cleanupInterval = setInterval(() => {
47
+ const now = Date.now();
48
+ let cleaned = 0;
49
+ for (const [key, entry] of this.entries) {
50
+ if (now - entry.windowStart > this.windowMs * 2) {
51
+ this.entries.delete(key);
52
+ cleaned++;
53
+ }
54
+ }
55
+ if (cleaned > 0) {
56
+ logger.debug('Rate limiter cleanup', { entriesRemoved: cleaned, remaining: this.entries.size });
57
+ }
58
+ }, this.windowMs);
59
+ }
60
+ /**
61
+ * Stop cleanup interval
62
+ */
63
+ stop() {
64
+ if (this.cleanupInterval) {
65
+ clearInterval(this.cleanupInterval);
66
+ this.cleanupInterval = null;
67
+ }
68
+ }
69
+ /**
70
+ * Check if request should be allowed
71
+ */
72
+ check(req) {
73
+ const url = req.url ?? '/';
74
+ const path = url.split('?')[0];
75
+ // Skip rate limiting for certain paths
76
+ if (this.skipPaths.has(path)) {
77
+ return { allowed: true, remaining: this.maxRequests, resetTime: 0 };
78
+ }
79
+ const key = this.keyGenerator(req);
80
+ const now = Date.now();
81
+ let entry = this.entries.get(key);
82
+ // Create new entry or reset if window expired
83
+ if (!entry || now - entry.windowStart > this.windowMs) {
84
+ entry = { count: 0, windowStart: now };
85
+ this.entries.set(key, entry);
86
+ }
87
+ // Increment count
88
+ entry.count++;
89
+ const remaining = Math.max(0, this.maxRequests - entry.count);
90
+ const resetTime = entry.windowStart + this.windowMs;
91
+ if (entry.count > this.maxRequests) {
92
+ logger.warn('Rate limit exceeded', {
93
+ key,
94
+ count: entry.count,
95
+ limit: this.maxRequests,
96
+ path,
97
+ });
98
+ return { allowed: false, remaining: 0, resetTime };
99
+ }
100
+ return { allowed: true, remaining, resetTime };
101
+ }
102
+ /**
103
+ * Middleware function for HTTP server
104
+ */
105
+ middleware() {
106
+ return (req, res) => {
107
+ const result = this.check(req);
108
+ // Add rate limit headers
109
+ res.setHeader('X-RateLimit-Limit', this.maxRequests.toString());
110
+ res.setHeader('X-RateLimit-Remaining', result.remaining.toString());
111
+ res.setHeader('X-RateLimit-Reset', Math.ceil(result.resetTime / 1000).toString());
112
+ if (!result.allowed) {
113
+ res.setHeader('Retry-After', Math.ceil((result.resetTime - Date.now()) / 1000).toString());
114
+ res.writeHead(429, { 'Content-Type': 'application/json' });
115
+ res.end(JSON.stringify({
116
+ error: 'Too Many Requests',
117
+ message: 'Rate limit exceeded. Please try again later.',
118
+ retryAfter: Math.ceil((result.resetTime - Date.now()) / 1000),
119
+ }));
120
+ return false;
121
+ }
122
+ return true;
123
+ };
124
+ }
125
+ /**
126
+ * Get current stats
127
+ */
128
+ getStats() {
129
+ return {
130
+ totalEntries: this.entries.size,
131
+ config: {
132
+ windowMs: this.windowMs,
133
+ maxRequests: this.maxRequests,
134
+ },
135
+ };
136
+ }
137
+ /**
138
+ * Reset rate limit for a specific key
139
+ */
140
+ reset(key) {
141
+ return this.entries.delete(key);
142
+ }
143
+ /**
144
+ * Clear all rate limit entries
145
+ */
146
+ clear() {
147
+ this.entries.clear();
148
+ }
149
+ }
150
+ /**
151
+ * Create a rate limiter instance with default config
152
+ */
153
+ export function createRateLimiter(config) {
154
+ return new RateLimiter(config);
155
+ }
156
+ //# sourceMappingURL=rateLimiter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rateLimiter.js","sourceRoot":"","sources":["../../src/server/rateLimiter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * SSE (Server-Sent Events) transport for MCP server
3
+ * Implements the legacy MCP protocol version 2024-11-05
4
+ */
5
+ import type { IncomingMessage, ServerResponse } from 'node:http';
6
+ import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
7
+ import type { EnvironmentConfig } from '../config.js';
8
+ import type { HaClient } from '../haClient/index.js';
9
+ import type { LocalAIClient } from '../localAI/index.js';
10
+ import { createServer } from './common.js';
11
+ interface SSETransportState {
12
+ transport: SSEServerTransport;
13
+ server: ReturnType<typeof createServer>;
14
+ }
15
+ /**
16
+ * Creates an SSE transport for handling HTTP+SSE connections
17
+ */
18
+ export declare function createSseTransport(client: HaClient, config: EnvironmentConfig, endpoint: string, res: ServerResponse, aiClient?: LocalAIClient): SSETransportState;
19
+ /**
20
+ * Handles SSE connection establishment (GET request)
21
+ */
22
+ export declare function handleSseConnection(client: HaClient, config: EnvironmentConfig, endpoint: string, req: IncomingMessage, res: ServerResponse, aiClient?: LocalAIClient): Promise<SSETransportState>;
23
+ /**
24
+ * Handles SSE message POST requests
25
+ */
26
+ export declare function handleSseMessage(transport: SSEServerTransport, req: IncomingMessage, res: ServerResponse, parsedBody?: unknown): Promise<void>;
27
+ /**
28
+ * Returns the message endpoint path for SSE transport
29
+ */
30
+ export declare function getSseMessagePath(): string;
31
+ export type { SSETransportState };
32
+ //# sourceMappingURL=sse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sse.d.ts","sourceRoot":"","sources":["../../src/server/sse.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAC;AAC7E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAI3C,UAAU,iBAAiB;IACzB,SAAS,EAAE,kBAAkB,CAAC;IAC9B,MAAM,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;CACzC;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,QAAQ,EAChB,MAAM,EAAE,iBAAiB,EACzB,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,cAAc,EACnB,QAAQ,CAAC,EAAE,aAAa,GACvB,iBAAiB,CAgBnB;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,QAAQ,EAChB,MAAM,EAAE,iBAAiB,EACzB,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,QAAQ,CAAC,EAAE,aAAa,GACvB,OAAO,CAAC,iBAAiB,CAAC,CA+B5B;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,kBAAkB,EAC7B,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,UAAU,CAAC,EAAE,OAAO,GACnB,OAAO,CAAC,IAAI,CAAC,CAWf;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAGD,YAAY,EAAE,iBAAiB,EAAE,CAAC"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * SSE (Server-Sent Events) transport for MCP server
3
+ * Implements the legacy MCP protocol version 2024-11-05
4
+ */
5
+ import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
6
+ import { logger } from '../utils/logger.js';
7
+ import { createServer } from './common.js';
8
+ const MESSAGE_PATH = '/messages';
9
+ /**
10
+ * Creates an SSE transport for handling HTTP+SSE connections
11
+ */
12
+ export function createSseTransport(client, config, endpoint, res, aiClient) {
13
+ const mcpServer = createServer(client, aiClient);
14
+ const transport = new SSEServerTransport(endpoint, res, {
15
+ allowedOrigins: config.httpAllowedOrigins,
16
+ enableDnsRebindingProtection: true,
17
+ });
18
+ transport.onerror = (error) => {
19
+ logger.error('SSE transport error', {
20
+ error,
21
+ message: error.message,
22
+ });
23
+ };
24
+ return { transport, server: mcpServer };
25
+ }
26
+ /**
27
+ * Handles SSE connection establishment (GET request)
28
+ */
29
+ export async function handleSseConnection(client, config, endpoint, req, res, aiClient) {
30
+ const originHeader = req.headers.origin;
31
+ const hostHeader = req.headers.host;
32
+ logger.info('SSE connection request received', {
33
+ method: req.method,
34
+ url: req.url,
35
+ origin: originHeader ?? '(not set)',
36
+ host: hostHeader ?? '(not set)',
37
+ });
38
+ try {
39
+ const { transport, server } = createSseTransport(client, config, endpoint, res, aiClient);
40
+ await server.connect(transport);
41
+ await transport.start();
42
+ logger.info('SSE connection established', {
43
+ sessionId: transport.sessionId,
44
+ });
45
+ return { transport, server };
46
+ }
47
+ catch (error) {
48
+ logger.error('Failed to establish SSE connection', {
49
+ error,
50
+ origin: originHeader ?? '(not set)',
51
+ host: hostHeader ?? '(not set)',
52
+ allowedOrigins: config.httpAllowedOrigins,
53
+ });
54
+ throw error;
55
+ }
56
+ }
57
+ /**
58
+ * Handles SSE message POST requests
59
+ */
60
+ export async function handleSseMessage(transport, req, res, parsedBody) {
61
+ logger.debug('SSE message received', {
62
+ sessionId: transport.sessionId,
63
+ hasBody: !!parsedBody,
64
+ });
65
+ await transport.handlePostMessage(req, res, parsedBody);
66
+ logger.debug('SSE message handled', {
67
+ sessionId: transport.sessionId,
68
+ });
69
+ }
70
+ /**
71
+ * Returns the message endpoint path for SSE transport
72
+ */
73
+ export function getSseMessagePath() {
74
+ return MESSAGE_PATH;
75
+ }
76
+ //# sourceMappingURL=sse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sse.js","sourceRoot":"","sources":["../../src/server/sse.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Stdio transport for MCP server
3
+ * Used for Claude Desktop and other stdio-based clients
4
+ */
5
+ import type { HaClient } from '../haClient/index.js';
6
+ import type { LocalAIClient } from '../localAI/index.js';
7
+ export declare function startStdioServer(client: HaClient, aiClient?: LocalAIClient): Promise<void>;
8
+ //# sourceMappingURL=stdio.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stdio.d.ts","sourceRoot":"","sources":["../../src/server/stdio.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAIzD,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAUhG"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Stdio transport for MCP server
3
+ * Used for Claude Desktop and other stdio-based clients
4
+ */
5
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
6
+ import { logger } from '../utils/logger.js';
7
+ import { createServer } from './common.js';
8
+ export async function startStdioServer(client, aiClient) {
9
+ logger.info('Starting stdio server');
10
+ const server = createServer(client, aiClient);
11
+ const transport = new StdioServerTransport();
12
+ logger.info('Connecting stdio server');
13
+ await server.connect(transport);
14
+ logger.info('Stdio server connected and ready');
15
+ }
16
+ //# sourceMappingURL=stdio.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stdio.js","sourceRoot":"","sources":["../../src/server/stdio.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAGjF,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,MAAgB,EAAE,QAAwB;IAC/E,MAAM,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;IAErC,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC9C,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAE7C,MAAM,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;IACvC,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEhC,MAAM,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC;AAClD,CAAC"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Streamable HTTP transport for MCP server
3
+ * Implements the MCP protocol version 2025-03-26 (current/recommended)
4
+ */
5
+ import type { IncomingMessage, ServerResponse } from 'node:http';
6
+ import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
7
+ import type { EnvironmentConfig } from '../config.js';
8
+ import type { HaClient } from '../haClient/index.js';
9
+ import type { LocalAIClient } from '../localAI/index.js';
10
+ import { createServer } from './common.js';
11
+ interface StreamTransportState {
12
+ transport: StreamableHTTPServerTransport;
13
+ server: ReturnType<typeof createServer>;
14
+ }
15
+ export type { StreamTransportState };
16
+ /**
17
+ * Creates a Streamable HTTP transport
18
+ * This implements the MCP protocol version 2025-03-26
19
+ */
20
+ export declare function createStreamTransport(client: HaClient, config: EnvironmentConfig, aiClient?: LocalAIClient): StreamTransportState;
21
+ /**
22
+ * Handles incoming Streamable HTTP requests (GET, POST, DELETE)
23
+ * For stateful mode, transports should be stored and reused by the caller
24
+ */
25
+ export declare function handleStreamRequest(client: HaClient, config: EnvironmentConfig, req: IncomingMessage, res: ServerResponse, parsedBody?: unknown, existingTransport?: StreamTransportState, aiClient?: LocalAIClient): Promise<StreamTransportState | void>;
26
+ //# sourceMappingURL=stream.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../src/server/stream.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACjE,OAAO,EAAE,6BAA6B,EAAE,MAAM,oDAAoD,CAAC;AACnG,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,UAAU,oBAAoB;IAC5B,SAAS,EAAE,6BAA6B,CAAC;IACzC,MAAM,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;CACzC;AAGD,YAAY,EAAE,oBAAoB,EAAE,CAAC;AAErC;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,iBAAiB,EAAE,QAAQ,CAAC,EAAE,aAAa,GAAG,oBAAoB,CA8BjI;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,QAAQ,EAChB,MAAM,EAAE,iBAAiB,EACzB,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,UAAU,CAAC,EAAE,OAAO,EACpB,iBAAiB,CAAC,EAAE,oBAAoB,EACxC,QAAQ,CAAC,EAAE,aAAa,GACvB,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CA0CtC"}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Streamable HTTP transport for MCP server
3
+ * Implements the MCP protocol version 2025-03-26 (current/recommended)
4
+ */
5
+ import { randomUUID } from 'node:crypto';
6
+ import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
7
+ import { logger } from '../utils/logger.js';
8
+ import { createServer } from './common.js';
9
+ /**
10
+ * Creates a Streamable HTTP transport
11
+ * This implements the MCP protocol version 2025-03-26
12
+ */
13
+ export function createStreamTransport(client, config, aiClient) {
14
+ const mcpServer = createServer(client, aiClient);
15
+ const enableStatefulSessions = config.stateful;
16
+ const sessionIdGenerator = enableStatefulSessions ? () => randomUUID() : undefined;
17
+ if (!enableStatefulSessions) {
18
+ logger.info('Starting Streamable HTTP transport in stateless mode; Mcp-Session-Id headers are optional');
19
+ }
20
+ const transport = new StreamableHTTPServerTransport({
21
+ sessionIdGenerator,
22
+ allowedOrigins: config.httpAllowedOrigins,
23
+ enableDnsRebindingProtection: true,
24
+ onsessioninitialized: (sessionId) => {
25
+ logger.info('Session initialized', { sessionId });
26
+ },
27
+ onsessionclosed: (sessionId) => {
28
+ logger.info('Session closed', { sessionId });
29
+ },
30
+ });
31
+ transport.onerror = (error) => {
32
+ logger.error('Streamable HTTP transport error', {
33
+ error,
34
+ message: error.message,
35
+ });
36
+ };
37
+ return { transport, server: mcpServer };
38
+ }
39
+ /**
40
+ * Handles incoming Streamable HTTP requests (GET, POST, DELETE)
41
+ * For stateful mode, transports should be stored and reused by the caller
42
+ */
43
+ export async function handleStreamRequest(client, config, req, res, parsedBody, existingTransport, aiClient) {
44
+ const originHeader = req.headers.origin;
45
+ const hostHeader = req.headers.host;
46
+ logger.info('Streamable HTTP request received', {
47
+ method: req.method,
48
+ url: req.url,
49
+ sessionId: req.headers['mcp-session-id'] ?? undefined,
50
+ origin: originHeader ?? '(not set)',
51
+ host: hostHeader ?? '(not set)',
52
+ });
53
+ // Reuse existing transport if provided, otherwise create new one
54
+ const state = existingTransport ?? createStreamTransport(client, config, aiClient);
55
+ if (!existingTransport) {
56
+ await state.server.connect(state.transport);
57
+ }
58
+ try {
59
+ await state.transport.handleRequest(req, res, parsedBody);
60
+ logger.debug('Streamable HTTP request handled', {
61
+ method: req.method,
62
+ sessionId: req.headers['mcp-session-id'] ?? undefined,
63
+ });
64
+ }
65
+ catch (error) {
66
+ logger.error('Failed to handle Streamable HTTP request', {
67
+ error,
68
+ method: req.method,
69
+ url: req.url,
70
+ origin: originHeader ?? '(not set)',
71
+ host: hostHeader ?? '(not set)',
72
+ allowedOrigins: config.httpAllowedOrigins,
73
+ });
74
+ throw error;
75
+ }
76
+ // Return state for session management if stateful
77
+ if (config.stateful) {
78
+ return state;
79
+ }
80
+ }
81
+ //# sourceMappingURL=stream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream.js","sourceRoot":"","sources":["../../src/server/stream.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * MCP Server setup and initialization
3
+ */
4
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
5
+ import type { HaClient } from './haClient.js';
6
+ export declare function createMcpServer(client: HaClient): Promise<Server>;
7
+ export declare function startStdioServer(client: HaClient): Promise<void>;
8
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAEnE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAI9C,wBAAsB,eAAe,CAAC,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAqBvE;AAED,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAStE"}
package/dist/server.js ADDED
@@ -0,0 +1,30 @@
1
+ /**
2
+ * MCP Server setup and initialization
3
+ */
4
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
5
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
6
+ import { registerAllTools } from './tools/registry.js';
7
+ import { logger } from './utils/logger.js';
8
+ export async function createMcpServer(client) {
9
+ logger.info('Creating MCP server');
10
+ const server = new Server({
11
+ name: 'ha-mcp',
12
+ version: '0.1.0',
13
+ }, {
14
+ capabilities: {
15
+ tools: {},
16
+ },
17
+ });
18
+ // Register all tools
19
+ registerAllTools(server, client);
20
+ logger.info('MCP server created with 5 tools registered');
21
+ return server;
22
+ }
23
+ export async function startStdioServer(client) {
24
+ logger.info('Starting MCP server with stdio transport');
25
+ const server = await createMcpServer(client);
26
+ const transport = new StdioServerTransport();
27
+ await server.connect(transport);
28
+ logger.info('MCP server connected and ready');
29
+ }
30
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAEjF,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAE3C,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,MAAgB;IACpD,MAAM,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;IAEnC,MAAM,MAAM,GAAG,IAAI,MAAM,CACvB;QACE,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,OAAO;KACjB,EACD;QACE,YAAY,EAAE;YACZ,KAAK,EAAE,EAAE;SACV;KACF,CACF,CAAC;IAEF,qBAAqB;IACrB,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEjC,MAAM,CAAC,IAAI,CAAC,4CAA4C,CAAC,CAAC;IAE1D,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,MAAgB;IACrD,MAAM,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC;IAExD,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,MAAM,CAAC,CAAC;IAC7C,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAE7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEhC,MAAM,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC;AAChD,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Call Service Tool
3
+ * Calls a Home Assistant service
4
+ */
5
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
6
+ import type { HaClient } from '../haClient/index.js';
7
+ export declare function registerCallServiceTool(server: Server, client: HaClient): void;
8
+ //# sourceMappingURL=callService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"callService.d.ts","sourceRoot":"","sources":["../../src/tools/callService.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAKnE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAIrD,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAG,IAAI,CAmG9E"}
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Call Service Tool
3
+ * Calls a Home Assistant service
4
+ */
5
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
6
+ import { logger } from '../utils/logger.js';
7
+ export function registerCallServiceTool(server, client) {
8
+ logger.debug('Registering callService tool');
9
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
10
+ return {
11
+ tools: [
12
+ {
13
+ name: 'callService',
14
+ description: 'Call a Home Assistant service (e.g., turn on a light, set temperature).',
15
+ inputSchema: {
16
+ type: 'object',
17
+ properties: {
18
+ domain: {
19
+ type: 'string',
20
+ description: 'Service domain (e.g., "light", "switch", "climate", "notify")',
21
+ },
22
+ service: {
23
+ type: 'string',
24
+ description: 'Service name (e.g., "turn_on", "turn_off", "set_temperature")',
25
+ },
26
+ service_data: {
27
+ type: 'object',
28
+ description: 'Optional service data (e.g., {"brightness": 255})',
29
+ },
30
+ target: {
31
+ type: 'object',
32
+ description: 'Optional target (entity_id, device_id, or area_id)',
33
+ properties: {
34
+ entity_id: {
35
+ type: ['string', 'array'],
36
+ description: 'Entity ID or array of entity IDs',
37
+ },
38
+ },
39
+ },
40
+ },
41
+ required: ['domain', 'service'],
42
+ },
43
+ },
44
+ ],
45
+ };
46
+ });
47
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
48
+ if (request.params.name !== 'callService') {
49
+ return {
50
+ content: [
51
+ {
52
+ type: 'text',
53
+ text: JSON.stringify({ error: 'Unknown tool' }),
54
+ },
55
+ ],
56
+ isError: true,
57
+ };
58
+ }
59
+ try {
60
+ const args = request.params.arguments;
61
+ if (!args.domain || !args.service) {
62
+ throw new Error('domain and service are required');
63
+ }
64
+ logger.info('Executing callService tool', {
65
+ domain: args.domain,
66
+ service: args.service,
67
+ });
68
+ const result = await client.callService(args);
69
+ return {
70
+ content: [
71
+ {
72
+ type: 'text',
73
+ text: JSON.stringify({
74
+ success: true,
75
+ context: result.context,
76
+ }, null, 2),
77
+ },
78
+ ],
79
+ };
80
+ }
81
+ catch (error) {
82
+ logger.error('Failed to call service', {
83
+ error: error instanceof Error ? error.message : String(error),
84
+ });
85
+ return {
86
+ content: [
87
+ {
88
+ type: 'text',
89
+ text: JSON.stringify({
90
+ error: 'Failed to call service',
91
+ message: error instanceof Error ? error.message : String(error),
92
+ }),
93
+ },
94
+ ],
95
+ isError: true,
96
+ };
97
+ }
98
+ });
99
+ }
100
+ //# sourceMappingURL=callService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"callService.js","sourceRoot":"","sources":["../../src/tools/callService.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Get Client Tool
3
+ * Get details for a specific client by MAC address
4
+ */
5
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
6
+ import type { OmadaClient } from '../omadaClient.js';
7
+ export declare function registerGetClientTool(server: Server, client: OmadaClient): void;
8
+ //# sourceMappingURL=getClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getClient.d.ts","sourceRoot":"","sources":["../../src/tools/getClient.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAKnE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGrD,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,IAAI,CAgG/E"}