@mp-consulting/homebridge-ai-kit 2.0.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.
- package/README.md +273 -0
- package/config.schema.json +131 -0
- package/dist/agent/run-agent.d.ts +61 -0
- package/dist/agent/run-agent.d.ts.map +1 -0
- package/dist/agent/run-agent.js +92 -0
- package/dist/agent/run-agent.js.map +1 -0
- package/dist/bin/homebridge-ai-kit.d.ts +3 -0
- package/dist/bin/homebridge-ai-kit.d.ts.map +1 -0
- package/dist/bin/homebridge-ai-kit.js +61 -0
- package/dist/bin/homebridge-ai-kit.js.map +1 -0
- package/dist/bin/homebridge-mcp-server.d.ts +3 -0
- package/dist/bin/homebridge-mcp-server.d.ts.map +1 -0
- package/dist/bin/homebridge-mcp-server.js +5 -0
- package/dist/bin/homebridge-mcp-server.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/create-server.d.ts +17 -0
- package/dist/mcp/create-server.d.ts.map +1 -0
- package/dist/mcp/create-server.js +42 -0
- package/dist/mcp/create-server.js.map +1 -0
- package/dist/mcp/homebridge-client.d.ts +105 -0
- package/dist/mcp/homebridge-client.d.ts.map +1 -0
- package/dist/mcp/homebridge-client.js +341 -0
- package/dist/mcp/homebridge-client.js.map +1 -0
- package/dist/mcp/http.d.ts +26 -0
- package/dist/mcp/http.d.ts.map +1 -0
- package/dist/mcp/http.js +124 -0
- package/dist/mcp/http.js.map +1 -0
- package/dist/mcp/index.d.ts +12 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +7 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/live.d.ts +46 -0
- package/dist/mcp/live.d.ts.map +1 -0
- package/dist/mcp/live.js +105 -0
- package/dist/mcp/live.js.map +1 -0
- package/dist/mcp/prompts.d.ts +4 -0
- package/dist/mcp/prompts.d.ts.map +1 -0
- package/dist/mcp/prompts.js +21 -0
- package/dist/mcp/prompts.js.map +1 -0
- package/dist/mcp/regex-search.d.ts +11 -0
- package/dist/mcp/regex-search.d.ts.map +1 -0
- package/dist/mcp/regex-search.js +53 -0
- package/dist/mcp/regex-search.js.map +1 -0
- package/dist/mcp/resources.d.ts +16 -0
- package/dist/mcp/resources.d.ts.map +1 -0
- package/dist/mcp/resources.js +65 -0
- package/dist/mcp/resources.js.map +1 -0
- package/dist/mcp/stdio.d.ts +11 -0
- package/dist/mcp/stdio.d.ts.map +1 -0
- package/dist/mcp/stdio.js +56 -0
- package/dist/mcp/stdio.js.map +1 -0
- package/dist/mcp/tools/accessories.d.ts +15 -0
- package/dist/mcp/tools/accessories.d.ts.map +1 -0
- package/dist/mcp/tools/accessories.js +179 -0
- package/dist/mcp/tools/accessories.js.map +1 -0
- package/dist/mcp/tools/child-bridges.d.ts +3 -0
- package/dist/mcp/tools/child-bridges.d.ts.map +1 -0
- package/dist/mcp/tools/child-bridges.js +28 -0
- package/dist/mcp/tools/child-bridges.js.map +1 -0
- package/dist/mcp/tools/config.d.ts +7 -0
- package/dist/mcp/tools/config.d.ts.map +1 -0
- package/dist/mcp/tools/config.js +111 -0
- package/dist/mcp/tools/config.js.map +1 -0
- package/dist/mcp/tools/helpers.d.ts +31 -0
- package/dist/mcp/tools/helpers.d.ts.map +1 -0
- package/dist/mcp/tools/helpers.js +49 -0
- package/dist/mcp/tools/helpers.js.map +1 -0
- package/dist/mcp/tools/logs.d.ts +7 -0
- package/dist/mcp/tools/logs.d.ts.map +1 -0
- package/dist/mcp/tools/logs.js +122 -0
- package/dist/mcp/tools/logs.js.map +1 -0
- package/dist/mcp/tools/plugin-jobs.d.ts +11 -0
- package/dist/mcp/tools/plugin-jobs.d.ts.map +1 -0
- package/dist/mcp/tools/plugin-jobs.js +75 -0
- package/dist/mcp/tools/plugin-jobs.js.map +1 -0
- package/dist/mcp/tools/plugins.d.ts +3 -0
- package/dist/mcp/tools/plugins.d.ts.map +1 -0
- package/dist/mcp/tools/plugins.js +74 -0
- package/dist/mcp/tools/plugins.js.map +1 -0
- package/dist/mcp/tools/server.d.ts +3 -0
- package/dist/mcp/tools/server.d.ts.map +1 -0
- package/dist/mcp/tools/server.js +69 -0
- package/dist/mcp/tools/server.js.map +1 -0
- package/dist/mcp/tools/system.d.ts +3 -0
- package/dist/mcp/tools/system.d.ts.map +1 -0
- package/dist/mcp/tools/system.js +9 -0
- package/dist/mcp/tools/system.js.map +1 -0
- package/dist/mcp/types.d.ts +75 -0
- package/dist/mcp/types.d.ts.map +1 -0
- package/dist/mcp/types.js +2 -0
- package/dist/mcp/types.js.map +1 -0
- package/dist/plugin/index.d.ts +7 -0
- package/dist/plugin/index.d.ts.map +1 -0
- package/dist/plugin/index.js +5 -0
- package/dist/plugin/index.js.map +1 -0
- package/dist/plugin/platform.d.ts +28 -0
- package/dist/plugin/platform.d.ts.map +1 -0
- package/dist/plugin/platform.js +76 -0
- package/dist/plugin/platform.js.map +1 -0
- package/dist/plugin/snippets.d.ts +27 -0
- package/dist/plugin/snippets.d.ts.map +1 -0
- package/dist/plugin/snippets.js +33 -0
- package/dist/plugin/snippets.js.map +1 -0
- package/homebridge-ui/public/index.html +164 -0
- package/homebridge-ui/public/js/app.js +200 -0
- package/homebridge-ui/public/lib/ai.css +738 -0
- package/homebridge-ui/public/lib/bootstrap-icons.min.css +5 -0
- package/homebridge-ui/public/lib/bootstrap.bundle.min.js +6 -0
- package/homebridge-ui/public/lib/bootstrap.min.css +5 -0
- package/homebridge-ui/public/lib/fonts/bootstrap-icons.woff +0 -0
- package/homebridge-ui/public/lib/fonts/bootstrap-icons.woff2 +0 -0
- package/homebridge-ui/public/lib/kit.css +994 -0
- package/homebridge-ui/public/lib/kit.js +794 -0
- package/homebridge-ui/server.js +28 -0
- package/package.json +94 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"homebridge-mcp-server.d.ts","sourceRoot":"","sources":["../../src/bin/homebridge-mcp-server.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"homebridge-mcp-server.js","sourceRoot":"","sources":["../../src/bin/homebridge-mcp-server.ts"],"names":[],"mappings":";AAEA,4EAA4E;AAC5E,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEjD,MAAM,cAAc,CAAC,uBAAuB,CAAC,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from '@mp-consulting/homebridge-ai-core';
|
|
2
|
+
export { runAgent } from './agent/run-agent.js';
|
|
3
|
+
export type { AgentEvent, AgentResult, AgentToolCall, RunAgentOptions } from './agent/run-agent.js';
|
|
4
|
+
/** Homebridge plugin entry point. */
|
|
5
|
+
declare const _default: (api: {
|
|
6
|
+
registerPlatform(name: string, constructor: unknown): void;
|
|
7
|
+
}) => void;
|
|
8
|
+
export default _default;
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,cAAc,mCAAmC,CAAC;AAGlD,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEpG,qCAAqC;yBACrB,KAAK;IAAE,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,GAAG,IAAI,CAAA;CAAE,KAAG,IAAI;AAA1F,wBAEE"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { PLATFORM_NAME } from '@mp-consulting/homebridge-ai-core';
|
|
2
|
+
import { AiKitPlatform } from './plugin/platform.js';
|
|
3
|
+
// ── AI core: redaction, config, providers, features, utilities ──
|
|
4
|
+
// Everything from @mp-consulting/homebridge-ai-core, re-exported so existing imports keep working.
|
|
5
|
+
export * from '@mp-consulting/homebridge-ai-core';
|
|
6
|
+
// ── Agent ──
|
|
7
|
+
export { runAgent } from './agent/run-agent.js';
|
|
8
|
+
/** Homebridge plugin entry point. */
|
|
9
|
+
export default (api) => {
|
|
10
|
+
api.registerPlatform(PLATFORM_NAME, AiKitPlatform);
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAClE,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,mEAAmE;AACnE,mGAAmG;AACnG,cAAc,mCAAmC,CAAC;AAElD,cAAc;AACd,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAGhD,qCAAqC;AACrC,eAAe,CAAC,GAAmE,EAAQ,EAAE;IAC3F,GAAG,CAAC,gBAAgB,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;AACrD,CAAC,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import type { HomebridgeClient } from './homebridge-client.js';
|
|
3
|
+
import type { LiveSource } from './live.js';
|
|
4
|
+
export declare const VERSION: string;
|
|
5
|
+
export interface ServerOptions {
|
|
6
|
+
/** Register only tools annotated `readOnlyHint: true`. */
|
|
7
|
+
readOnly?: boolean;
|
|
8
|
+
/**
|
|
9
|
+
* Change feed behind `resources/subscribe`. Default: socket.io with polling
|
|
10
|
+
* fallback ({@link createLiveSource}); `false` disables subscriptions.
|
|
11
|
+
*/
|
|
12
|
+
live?: LiveSource | false;
|
|
13
|
+
}
|
|
14
|
+
export declare function createServer(client: HomebridgeClient, options?: ServerOptions): McpServer;
|
|
15
|
+
/** Parses a boolean env var: 1/true/yes/on (any case) are true, anything else is false. */
|
|
16
|
+
export declare function envFlag(value: string | undefined): boolean;
|
|
17
|
+
//# sourceMappingURL=create-server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-server.d.ts","sourceRoot":"","sources":["../../src/mcp/create-server.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAa/D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAM5C,eAAO,MAAM,OAAO,QAAU,CAAC;AAa/B,MAAM,WAAW,aAAa;IAC5B,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,IAAI,CAAC,EAAE,UAAU,GAAG,KAAK,CAAC;CAC3B;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,gBAAgB,EAAE,OAAO,GAAE,aAAkB,GAAG,SAAS,CAS7F;AAED,2FAA2F;AAC3F,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAE1D"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { createRequire } from 'node:module';
|
|
2
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
|
+
import { createRegistrar } from './tools/helpers.js';
|
|
4
|
+
import { register as registerAccessories } from './tools/accessories.js';
|
|
5
|
+
import { register as registerServer } from './tools/server.js';
|
|
6
|
+
import { register as registerConfig } from './tools/config.js';
|
|
7
|
+
import { register as registerPlugins } from './tools/plugins.js';
|
|
8
|
+
import { register as registerSystem } from './tools/system.js';
|
|
9
|
+
import { register as registerLogs } from './tools/logs.js';
|
|
10
|
+
import { register as registerPluginJobs } from './tools/plugin-jobs.js';
|
|
11
|
+
import { register as registerChildBridges } from './tools/child-bridges.js';
|
|
12
|
+
import { registerResources } from './resources.js';
|
|
13
|
+
import { registerPrompts } from './prompts.js';
|
|
14
|
+
import { createLiveSource } from './live.js';
|
|
15
|
+
// package.json sits two levels above both src/mcp/ and dist/mcp/, and ships in the npm tarball.
|
|
16
|
+
const { version } = createRequire(import.meta.url)('../../package.json');
|
|
17
|
+
export const VERSION = version;
|
|
18
|
+
const TOOL_GROUPS = [
|
|
19
|
+
registerAccessories,
|
|
20
|
+
registerServer,
|
|
21
|
+
registerConfig,
|
|
22
|
+
registerPlugins,
|
|
23
|
+
registerSystem,
|
|
24
|
+
registerLogs,
|
|
25
|
+
registerPluginJobs,
|
|
26
|
+
registerChildBridges,
|
|
27
|
+
];
|
|
28
|
+
export function createServer(client, options = {}) {
|
|
29
|
+
const server = new McpServer({ name: 'homebridge-ai-kit', version: VERSION });
|
|
30
|
+
const tool = createRegistrar(server, options);
|
|
31
|
+
for (const register of TOOL_GROUPS) {
|
|
32
|
+
register(tool, client);
|
|
33
|
+
}
|
|
34
|
+
registerResources(server, client, options.live ?? createLiveSource(client));
|
|
35
|
+
registerPrompts(server);
|
|
36
|
+
return server;
|
|
37
|
+
}
|
|
38
|
+
/** Parses a boolean env var: 1/true/yes/on (any case) are true, anything else is false. */
|
|
39
|
+
export function envFlag(value) {
|
|
40
|
+
return /^(1|true|yes|on)$/i.test(value?.trim() ?? '');
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=create-server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-server.js","sourceRoot":"","sources":["../../src/mcp/create-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGpE,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,QAAQ,IAAI,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AACzE,OAAO,EAAE,QAAQ,IAAI,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,QAAQ,IAAI,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,QAAQ,IAAI,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,EAAE,QAAQ,IAAI,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,QAAQ,IAAI,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC3D,OAAO,EAAE,QAAQ,IAAI,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AACxE,OAAO,EAAE,QAAQ,IAAI,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAC5E,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAE7C,gGAAgG;AAChG,MAAM,EAAE,OAAO,EAAE,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,oBAAoB,CAAwB,CAAC;AAEhG,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC;AAE/B,MAAM,WAAW,GAAoB;IACnC,mBAAmB;IACnB,cAAc;IACd,cAAc;IACd,eAAe;IACf,cAAc;IACd,YAAY;IACZ,kBAAkB;IAClB,oBAAoB;CACrB,CAAC;AAYF,MAAM,UAAU,YAAY,CAAC,MAAwB,EAAE,UAAyB,EAAE;IAChF,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,EAAE,IAAI,EAAE,mBAAmB,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;IAC9E,MAAM,IAAI,GAAG,eAAe,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9C,KAAK,MAAM,QAAQ,IAAI,WAAW,EAAE,CAAC;QACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACzB,CAAC;IACD,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,IAAI,IAAI,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC;IAC5E,eAAe,CAAC,MAAM,CAAC,CAAC;IACxB,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,2FAA2F;AAC3F,MAAM,UAAU,OAAO,CAAC,KAAyB;IAC/C,OAAO,oBAAoB,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;AACxD,CAAC"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP client for the Homebridge Config UI REST API.
|
|
3
|
+
* Handles JWT authentication, token refresh, and all API calls.
|
|
4
|
+
*/
|
|
5
|
+
import type { Accessory, CachedAccessory, ChildBridge, Plugin, PluginJob, Room } from './types.js';
|
|
6
|
+
export interface LogTail {
|
|
7
|
+
/** The last `maxBytes` of the log, decoded as UTF-8. May start mid-line when truncated. */
|
|
8
|
+
text: string;
|
|
9
|
+
truncated: boolean;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Returns a warning when credentials would cross the network unencrypted, i.e.
|
|
13
|
+
* plain http to something other than a loopback or private-range host.
|
|
14
|
+
*/
|
|
15
|
+
export declare function insecureTransportWarning(url: URL): string | null;
|
|
16
|
+
export interface HomebridgeClientOptions {
|
|
17
|
+
/** Homebridge UI URL. Default: `HOMEBRIDGE_URL`. */
|
|
18
|
+
url?: string;
|
|
19
|
+
/** Default: `HOMEBRIDGE_USERNAME`. Not needed with a token. */
|
|
20
|
+
username?: string;
|
|
21
|
+
/** Default: `HOMEBRIDGE_PASSWORD`. Not needed with a token. */
|
|
22
|
+
password?: string;
|
|
23
|
+
/** A Homebridge UI API token (Glass UI `hbg_…`). Default: `HOMEBRIDGE_TOKEN`. Replaces username/password. */
|
|
24
|
+
token?: string;
|
|
25
|
+
/** Supplies a (short-lived) token per request, e.g. the current user's JWT. Takes precedence over everything else. */
|
|
26
|
+
getToken?: () => Promise<string>;
|
|
27
|
+
/** Per-request timeout. Default: `HOMEBRIDGE_TIMEOUT_MS`, else 30000. */
|
|
28
|
+
timeoutMs?: number;
|
|
29
|
+
/** The fetch to call Homebridge with, e.g. one that trusts a self-signed certificate. Default: the global fetch. */
|
|
30
|
+
fetch?: typeof fetch;
|
|
31
|
+
}
|
|
32
|
+
export declare class HomebridgeClient {
|
|
33
|
+
private readonly baseUrl;
|
|
34
|
+
private readonly auth;
|
|
35
|
+
private readonly timeoutMs;
|
|
36
|
+
private readonly fetchImpl;
|
|
37
|
+
private token;
|
|
38
|
+
/** In-flight login/refresh, shared so concurrent callers don't each log in. */
|
|
39
|
+
private renewal;
|
|
40
|
+
constructor(options?: HomebridgeClientOptions);
|
|
41
|
+
/** The Homebridge UI base URL, without a trailing slash. */
|
|
42
|
+
get url(): string;
|
|
43
|
+
/** A warning to surface at startup if the configured URL is unsafe, else null. */
|
|
44
|
+
get transportWarning(): string | null;
|
|
45
|
+
/** fetch with a timeout, turning network failures into readable errors. */
|
|
46
|
+
private send;
|
|
47
|
+
private authenticate;
|
|
48
|
+
private refreshToken;
|
|
49
|
+
/**
|
|
50
|
+
* Replace `stale` with a fresh token (refresh, falling back to a full login).
|
|
51
|
+
* Concurrent callers share one renewal, and a caller whose stale token was
|
|
52
|
+
* already replaced by someone else returns immediately.
|
|
53
|
+
*/
|
|
54
|
+
private renewToken;
|
|
55
|
+
/** A token for the current credentials (logging in if needed), e.g. for a socket.io handshake. */
|
|
56
|
+
accessToken(): Promise<string>;
|
|
57
|
+
/** Authenticated request returning the raw response; throws on a non-2xx status. */
|
|
58
|
+
private fetchAuthed;
|
|
59
|
+
private request;
|
|
60
|
+
getAccessories(): Promise<Accessory[]>;
|
|
61
|
+
getAccessory(uniqueId: string): Promise<Accessory>;
|
|
62
|
+
getAccessoryLayout(): Promise<Room[]>;
|
|
63
|
+
setAccessoryCharacteristic(uniqueId: string, characteristicType: string, value: string | number | boolean): Promise<unknown>;
|
|
64
|
+
getHomebridgeStatus(): Promise<unknown>;
|
|
65
|
+
getServerInformation(): Promise<unknown>;
|
|
66
|
+
restartServer(): Promise<unknown>;
|
|
67
|
+
getPairingInfo(): Promise<unknown>;
|
|
68
|
+
getCachedAccessories(): Promise<CachedAccessory[]>;
|
|
69
|
+
/**
|
|
70
|
+
* @param cacheFile Which cache holds the accessory (`$cacheFile` from the list). Omit for the
|
|
71
|
+
* main bridge; child-bridge accessories live in their own file and can't be removed without it.
|
|
72
|
+
*/
|
|
73
|
+
removeCachedAccessory(uuid: string, cacheFile?: string): Promise<unknown>;
|
|
74
|
+
resetCachedAccessories(): Promise<unknown>;
|
|
75
|
+
getConfig(): Promise<Record<string, unknown>>;
|
|
76
|
+
updateConfig(config: unknown): Promise<unknown>;
|
|
77
|
+
getPlugins(): Promise<Plugin[]>;
|
|
78
|
+
searchPlugins(query: string): Promise<Plugin[]>;
|
|
79
|
+
lookupPlugin(pluginName: string): Promise<unknown>;
|
|
80
|
+
getPluginVersions(pluginName: string): Promise<unknown>;
|
|
81
|
+
getPluginConfigSchema(pluginName: string): Promise<unknown>;
|
|
82
|
+
getPluginChangelog(pluginName: string): Promise<unknown>;
|
|
83
|
+
/** Starts an install job (Glass UI). */
|
|
84
|
+
installPlugin(name: string, version?: string): Promise<{
|
|
85
|
+
jobId: string;
|
|
86
|
+
}>;
|
|
87
|
+
updatePlugin(name: string, version?: string): Promise<{
|
|
88
|
+
jobId: string;
|
|
89
|
+
}>;
|
|
90
|
+
uninstallPlugin(name: string): Promise<{
|
|
91
|
+
jobId: string;
|
|
92
|
+
}>;
|
|
93
|
+
getPluginJob(jobId: string): Promise<PluginJob>;
|
|
94
|
+
getChildBridges(): Promise<ChildBridge[]>;
|
|
95
|
+
/** @param deviceId The child bridge's username (`0E:3C:…` or without colons). */
|
|
96
|
+
controlChildBridge(action: 'restart' | 'stop' | 'start', deviceId: string): Promise<unknown>;
|
|
97
|
+
getSystemInfo(): Promise<unknown>;
|
|
98
|
+
/**
|
|
99
|
+
* Stream the Homebridge log file and keep only its last `maxBytes`, so a
|
|
100
|
+
* multi-hundred-MB log never has to sit in memory whole. The UI strips ANSI
|
|
101
|
+
* colour codes unless `colour=yes` is passed. Requires an hb-service install.
|
|
102
|
+
*/
|
|
103
|
+
getLogTail(maxBytes: number): Promise<LogTail>;
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=homebridge-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"homebridge-client.d.ts","sourceRoot":"","sources":["../../src/mcp/homebridge-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP client for the Homebridge Config UI REST API.
|
|
3
|
+
* Handles JWT authentication, token refresh, and all API calls.
|
|
4
|
+
*/
|
|
5
|
+
const DEFAULT_TIMEOUT_MS = 30_000;
|
|
6
|
+
/**
|
|
7
|
+
* Returns a warning when credentials would cross the network unencrypted, i.e.
|
|
8
|
+
* plain http to something other than a loopback or private-range host.
|
|
9
|
+
*/
|
|
10
|
+
export function insecureTransportWarning(url) {
|
|
11
|
+
if (url.protocol !== 'http:') {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
const host = url.hostname.replace(/^\[|\]$/g, '');
|
|
15
|
+
const local = host === 'localhost' ||
|
|
16
|
+
host.endsWith('.local') ||
|
|
17
|
+
host === '::1' ||
|
|
18
|
+
/^127\./.test(host) ||
|
|
19
|
+
/^10\./.test(host) ||
|
|
20
|
+
/^192\.168\./.test(host) ||
|
|
21
|
+
/^172\.(1[6-9]|2\d|3[01])\./.test(host) ||
|
|
22
|
+
/^f[cd][0-9a-f]{2}:/i.test(host);
|
|
23
|
+
return local
|
|
24
|
+
? null
|
|
25
|
+
: `HOMEBRIDGE_URL uses plain http to a non-local host (${url.host}); your Homebridge credentials will be sent unencrypted.`;
|
|
26
|
+
}
|
|
27
|
+
export class HomebridgeClient {
|
|
28
|
+
baseUrl;
|
|
29
|
+
auth;
|
|
30
|
+
timeoutMs;
|
|
31
|
+
fetchImpl;
|
|
32
|
+
token = null;
|
|
33
|
+
/** In-flight login/refresh, shared so concurrent callers don't each log in. */
|
|
34
|
+
renewal = null;
|
|
35
|
+
constructor(options = {}) {
|
|
36
|
+
const env = process.env;
|
|
37
|
+
const url = options.url ?? env.HOMEBRIDGE_URL;
|
|
38
|
+
const timeout = options.timeoutMs ?? env.HOMEBRIDGE_TIMEOUT_MS;
|
|
39
|
+
if (!url) {
|
|
40
|
+
throw new Error('HOMEBRIDGE_URL environment variable is required');
|
|
41
|
+
}
|
|
42
|
+
if (options.getToken) {
|
|
43
|
+
this.auth = { kind: 'provider', getToken: options.getToken };
|
|
44
|
+
}
|
|
45
|
+
else if (options.token ?? env.HOMEBRIDGE_TOKEN) {
|
|
46
|
+
this.auth = { kind: 'static', token: (options.token ?? env.HOMEBRIDGE_TOKEN) };
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
const username = options.username ?? env.HOMEBRIDGE_USERNAME;
|
|
50
|
+
const password = options.password ?? env.HOMEBRIDGE_PASSWORD;
|
|
51
|
+
if (!username) {
|
|
52
|
+
throw new Error('HOMEBRIDGE_USERNAME environment variable is required (or set HOMEBRIDGE_TOKEN)');
|
|
53
|
+
}
|
|
54
|
+
if (!password) {
|
|
55
|
+
throw new Error('HOMEBRIDGE_PASSWORD environment variable is required (or set HOMEBRIDGE_TOKEN)');
|
|
56
|
+
}
|
|
57
|
+
this.auth = { kind: 'login', username, password };
|
|
58
|
+
}
|
|
59
|
+
let parsed;
|
|
60
|
+
try {
|
|
61
|
+
parsed = new URL(url);
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
throw new Error(`HOMEBRIDGE_URL is not a valid URL: ${url}`);
|
|
65
|
+
}
|
|
66
|
+
if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
|
|
67
|
+
throw new Error(`HOMEBRIDGE_URL must use http or https, got ${parsed.protocol}`);
|
|
68
|
+
}
|
|
69
|
+
this.timeoutMs = timeout !== undefined && timeout !== '' ? Number(timeout) : DEFAULT_TIMEOUT_MS;
|
|
70
|
+
if (!Number.isFinite(this.timeoutMs) || this.timeoutMs <= 0) {
|
|
71
|
+
throw new Error(`HOMEBRIDGE_TIMEOUT_MS must be a positive number of milliseconds, got ${timeout}`);
|
|
72
|
+
}
|
|
73
|
+
this.baseUrl = url.replace(/\/+$/, '');
|
|
74
|
+
this.fetchImpl = options.fetch;
|
|
75
|
+
}
|
|
76
|
+
/** The Homebridge UI base URL, without a trailing slash. */
|
|
77
|
+
get url() {
|
|
78
|
+
return this.baseUrl;
|
|
79
|
+
}
|
|
80
|
+
/** A warning to surface at startup if the configured URL is unsafe, else null. */
|
|
81
|
+
get transportWarning() {
|
|
82
|
+
return insecureTransportWarning(new URL(this.baseUrl));
|
|
83
|
+
}
|
|
84
|
+
// ── Transport ───────────────────────────────────────────────────
|
|
85
|
+
/** fetch with a timeout, turning network failures into readable errors. */
|
|
86
|
+
async send(method, path, init = {}) {
|
|
87
|
+
try {
|
|
88
|
+
// The global is looked up per call, so it can be replaced after construction
|
|
89
|
+
return await (this.fetchImpl ?? fetch)(`${this.baseUrl}${path}`, {
|
|
90
|
+
...init,
|
|
91
|
+
method,
|
|
92
|
+
signal: AbortSignal.timeout(this.timeoutMs),
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
if (error instanceof Error && error.name === 'TimeoutError') {
|
|
97
|
+
throw new Error(`Homebridge did not respond within ${this.timeoutMs}ms (${method} ${path})`, { cause: error });
|
|
98
|
+
}
|
|
99
|
+
const cause = error instanceof Error && error.cause instanceof Error ? `: ${error.cause.message}` : '';
|
|
100
|
+
throw new Error(`Cannot reach Homebridge at ${this.baseUrl} (${method} ${path})${cause}`, { cause: error });
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
// ── Authentication ──────────────────────────────────────────────
|
|
104
|
+
async authenticate() {
|
|
105
|
+
if (this.auth.kind === 'static') {
|
|
106
|
+
this.token = this.auth.token;
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
if (this.auth.kind === 'provider') {
|
|
110
|
+
this.token = await this.auth.getToken();
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
const res = await this.send('POST', '/api/auth/login', {
|
|
114
|
+
headers: { 'Content-Type': 'application/json' },
|
|
115
|
+
body: JSON.stringify({ username: this.auth.username, password: this.auth.password }),
|
|
116
|
+
});
|
|
117
|
+
if (!res.ok) {
|
|
118
|
+
const body = await res.text();
|
|
119
|
+
throw new Error(`Authentication failed (${res.status}): ${body}`);
|
|
120
|
+
}
|
|
121
|
+
const data = (await res.json());
|
|
122
|
+
this.token = data.access_token;
|
|
123
|
+
}
|
|
124
|
+
async refreshToken() {
|
|
125
|
+
// API tokens cannot be refreshed; a token provider is simply asked again.
|
|
126
|
+
if (!this.token || this.auth.kind !== 'login') {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
try {
|
|
130
|
+
const res = await this.send('POST', '/api/auth/refresh', {
|
|
131
|
+
headers: {
|
|
132
|
+
'Content-Type': 'application/json',
|
|
133
|
+
Authorization: `Bearer ${this.token}`,
|
|
134
|
+
},
|
|
135
|
+
});
|
|
136
|
+
if (!res.ok) {
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
const data = (await res.json());
|
|
140
|
+
this.token = data.access_token;
|
|
141
|
+
return true;
|
|
142
|
+
}
|
|
143
|
+
catch {
|
|
144
|
+
return false;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Replace `stale` with a fresh token (refresh, falling back to a full login).
|
|
149
|
+
* Concurrent callers share one renewal, and a caller whose stale token was
|
|
150
|
+
* already replaced by someone else returns immediately.
|
|
151
|
+
*/
|
|
152
|
+
async renewToken(stale) {
|
|
153
|
+
if (this.token !== stale) {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
this.renewal ??= (async () => {
|
|
157
|
+
if (!(await this.refreshToken())) {
|
|
158
|
+
await this.authenticate();
|
|
159
|
+
}
|
|
160
|
+
})().finally(() => {
|
|
161
|
+
this.renewal = null;
|
|
162
|
+
});
|
|
163
|
+
await this.renewal;
|
|
164
|
+
}
|
|
165
|
+
// ── Generic request methods ─────────────────────────────────────
|
|
166
|
+
/** A token for the current credentials (logging in if needed), e.g. for a socket.io handshake. */
|
|
167
|
+
async accessToken() {
|
|
168
|
+
if (this.auth.kind === 'provider') {
|
|
169
|
+
return this.auth.getToken();
|
|
170
|
+
}
|
|
171
|
+
if (!this.token) {
|
|
172
|
+
await this.renewToken(null);
|
|
173
|
+
}
|
|
174
|
+
return this.token;
|
|
175
|
+
}
|
|
176
|
+
/** Authenticated request returning the raw response; throws on a non-2xx status. */
|
|
177
|
+
async fetchAuthed(method, path, body) {
|
|
178
|
+
if (this.auth.kind === 'provider') {
|
|
179
|
+
// Ask for a token on every request: the provider owns caching and expiry.
|
|
180
|
+
this.token = await this.auth.getToken();
|
|
181
|
+
}
|
|
182
|
+
else if (!this.token) {
|
|
183
|
+
await this.renewToken(null);
|
|
184
|
+
}
|
|
185
|
+
const doFetch = () => {
|
|
186
|
+
const headers = {
|
|
187
|
+
Authorization: `Bearer ${this.token}`,
|
|
188
|
+
};
|
|
189
|
+
if (body !== undefined) {
|
|
190
|
+
headers['Content-Type'] = 'application/json';
|
|
191
|
+
}
|
|
192
|
+
return this.send(method, path, {
|
|
193
|
+
headers,
|
|
194
|
+
body: body !== undefined ? JSON.stringify(body) : undefined,
|
|
195
|
+
});
|
|
196
|
+
};
|
|
197
|
+
const usedToken = this.token;
|
|
198
|
+
let res = await doFetch();
|
|
199
|
+
// On 401, renew the token (refresh, else re-login) and retry once
|
|
200
|
+
if (res.status === 401 && this.auth.kind !== 'static') {
|
|
201
|
+
await res.body?.cancel();
|
|
202
|
+
await this.renewToken(usedToken);
|
|
203
|
+
res = await doFetch();
|
|
204
|
+
}
|
|
205
|
+
if (!res.ok) {
|
|
206
|
+
const text = await res.text();
|
|
207
|
+
throw new Error(`Homebridge API error ${res.status} ${method} ${path}: ${text}`);
|
|
208
|
+
}
|
|
209
|
+
return res;
|
|
210
|
+
}
|
|
211
|
+
async request(method, path, body) {
|
|
212
|
+
const res = await this.fetchAuthed(method, path, body);
|
|
213
|
+
const contentType = res.headers.get('content-type') ?? '';
|
|
214
|
+
if (contentType.includes('application/json')) {
|
|
215
|
+
return (await res.json());
|
|
216
|
+
}
|
|
217
|
+
return (await res.text());
|
|
218
|
+
}
|
|
219
|
+
// ── Accessories ─────────────────────────────────────────────────
|
|
220
|
+
async getAccessories() {
|
|
221
|
+
return this.request('GET', '/api/accessories');
|
|
222
|
+
}
|
|
223
|
+
async getAccessory(uniqueId) {
|
|
224
|
+
return this.request('GET', `/api/accessories/${encodeURIComponent(uniqueId)}`);
|
|
225
|
+
}
|
|
226
|
+
async getAccessoryLayout() {
|
|
227
|
+
return this.request('GET', '/api/accessories/layout');
|
|
228
|
+
}
|
|
229
|
+
async setAccessoryCharacteristic(uniqueId, characteristicType, value) {
|
|
230
|
+
return this.request('PUT', `/api/accessories/${encodeURIComponent(uniqueId)}`, {
|
|
231
|
+
characteristicType,
|
|
232
|
+
value,
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
// ── Server / Status ─────────────────────────────────────────────
|
|
236
|
+
async getHomebridgeStatus() {
|
|
237
|
+
return this.request('GET', '/api/status/homebridge');
|
|
238
|
+
}
|
|
239
|
+
async getServerInformation() {
|
|
240
|
+
return this.request('GET', '/api/status/server-information');
|
|
241
|
+
}
|
|
242
|
+
async restartServer() {
|
|
243
|
+
return this.request('PUT', '/api/server/restart');
|
|
244
|
+
}
|
|
245
|
+
async getPairingInfo() {
|
|
246
|
+
return this.request('GET', '/api/server/pairing');
|
|
247
|
+
}
|
|
248
|
+
async getCachedAccessories() {
|
|
249
|
+
return this.request('GET', '/api/server/cached-accessories');
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* @param cacheFile Which cache holds the accessory (`$cacheFile` from the list). Omit for the
|
|
253
|
+
* main bridge; child-bridge accessories live in their own file and can't be removed without it.
|
|
254
|
+
*/
|
|
255
|
+
async removeCachedAccessory(uuid, cacheFile) {
|
|
256
|
+
const query = cacheFile ? `?cacheFile=${encodeURIComponent(cacheFile)}` : '';
|
|
257
|
+
return this.request('DELETE', `/api/server/cached-accessories/${encodeURIComponent(uuid)}${query}`);
|
|
258
|
+
}
|
|
259
|
+
async resetCachedAccessories() {
|
|
260
|
+
return this.request('PUT', '/api/server/reset-cached-accessories');
|
|
261
|
+
}
|
|
262
|
+
// ── Config ──────────────────────────────────────────────────────
|
|
263
|
+
async getConfig() {
|
|
264
|
+
return this.request('GET', '/api/config-editor');
|
|
265
|
+
}
|
|
266
|
+
async updateConfig(config) {
|
|
267
|
+
return this.request('POST', '/api/config-editor', config);
|
|
268
|
+
}
|
|
269
|
+
// ── Plugins ─────────────────────────────────────────────────────
|
|
270
|
+
async getPlugins() {
|
|
271
|
+
return this.request('GET', '/api/plugins');
|
|
272
|
+
}
|
|
273
|
+
async searchPlugins(query) {
|
|
274
|
+
return this.request('GET', `/api/plugins/search/${encodeURIComponent(query)}`);
|
|
275
|
+
}
|
|
276
|
+
async lookupPlugin(pluginName) {
|
|
277
|
+
return this.request('GET', `/api/plugins/lookup/${encodeURIComponent(pluginName)}`);
|
|
278
|
+
}
|
|
279
|
+
async getPluginVersions(pluginName) {
|
|
280
|
+
return this.request('GET', `/api/plugins/lookup/${encodeURIComponent(pluginName)}/versions`);
|
|
281
|
+
}
|
|
282
|
+
async getPluginConfigSchema(pluginName) {
|
|
283
|
+
return this.request('GET', `/api/plugins/config-schema/${encodeURIComponent(pluginName)}`);
|
|
284
|
+
}
|
|
285
|
+
async getPluginChangelog(pluginName) {
|
|
286
|
+
return this.request('GET', `/api/plugins/changelog/${encodeURIComponent(pluginName)}`);
|
|
287
|
+
}
|
|
288
|
+
/** Starts an install job (Glass UI). */
|
|
289
|
+
async installPlugin(name, version) {
|
|
290
|
+
return this.request('POST', '/api/plugins/install', { name, ...(version ? { version } : {}) });
|
|
291
|
+
}
|
|
292
|
+
async updatePlugin(name, version) {
|
|
293
|
+
return this.request('POST', '/api/plugins/update', { name, ...(version ? { version } : {}) });
|
|
294
|
+
}
|
|
295
|
+
async uninstallPlugin(name) {
|
|
296
|
+
return this.request('POST', '/api/plugins/uninstall', { name });
|
|
297
|
+
}
|
|
298
|
+
async getPluginJob(jobId) {
|
|
299
|
+
return this.request('GET', `/api/plugins/jobs/${encodeURIComponent(jobId)}`);
|
|
300
|
+
}
|
|
301
|
+
// ── Child bridges ───────────────────────────────────────────────
|
|
302
|
+
async getChildBridges() {
|
|
303
|
+
return this.request('GET', '/api/status/homebridge/child-bridges');
|
|
304
|
+
}
|
|
305
|
+
/** @param deviceId The child bridge's username (`0E:3C:…` or without colons). */
|
|
306
|
+
async controlChildBridge(action, deviceId) {
|
|
307
|
+
return this.request('PUT', `/api/server/${action}/${encodeURIComponent(deviceId)}`);
|
|
308
|
+
}
|
|
309
|
+
// ── Platform Tools ──────────────────────────────────────────────
|
|
310
|
+
async getSystemInfo() {
|
|
311
|
+
return this.request('GET', '/api/platform-tools/system-information');
|
|
312
|
+
}
|
|
313
|
+
// ── Logs ────────────────────────────────────────────────────────
|
|
314
|
+
/**
|
|
315
|
+
* Stream the Homebridge log file and keep only its last `maxBytes`, so a
|
|
316
|
+
* multi-hundred-MB log never has to sit in memory whole. The UI strips ANSI
|
|
317
|
+
* colour codes unless `colour=yes` is passed. Requires an hb-service install.
|
|
318
|
+
*/
|
|
319
|
+
async getLogTail(maxBytes) {
|
|
320
|
+
const res = await this.fetchAuthed('GET', '/api/platform-tools/hb-service/log/download');
|
|
321
|
+
if (!res.body) {
|
|
322
|
+
return { text: '', truncated: false };
|
|
323
|
+
}
|
|
324
|
+
const chunks = [];
|
|
325
|
+
let kept = 0;
|
|
326
|
+
let total = 0;
|
|
327
|
+
for await (const chunk of res.body) {
|
|
328
|
+
chunks.push(chunk);
|
|
329
|
+
kept += chunk.byteLength;
|
|
330
|
+
total += chunk.byteLength;
|
|
331
|
+
// Drop whole leading chunks that are no longer needed to cover maxBytes.
|
|
332
|
+
while (chunks.length > 1 && kept - chunks[0].byteLength >= maxBytes) {
|
|
333
|
+
kept -= chunks.shift().byteLength;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
const buffer = Buffer.concat(chunks);
|
|
337
|
+
const tail = buffer.byteLength > maxBytes ? buffer.subarray(buffer.byteLength - maxBytes) : buffer;
|
|
338
|
+
return { text: tail.toString('utf8'), truncated: total > maxBytes };
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
//# sourceMappingURL=homebridge-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"homebridge-client.js","sourceRoot":"","sources":["../../src/mcp/homebridge-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Streamable HTTP transport for outside MCP clients. Every request needs
|
|
3
|
+
* `Authorization: Bearer <token>`; each MCP session gets its own server.
|
|
4
|
+
*/
|
|
5
|
+
import type { Server } from 'node:http';
|
|
6
|
+
import type { HomebridgeClient } from './homebridge-client.js';
|
|
7
|
+
import type { LiveSource } from './live.js';
|
|
8
|
+
export declare const MCP_PATH = "/mcp";
|
|
9
|
+
export interface HttpServerOptions {
|
|
10
|
+
port?: number;
|
|
11
|
+
/** Default 127.0.0.1. Binding elsewhere exposes Homebridge control to the network. */
|
|
12
|
+
host?: string;
|
|
13
|
+
/** Bearer token every request must carry. Required. */
|
|
14
|
+
token: string;
|
|
15
|
+
client: HomebridgeClient;
|
|
16
|
+
readOnly?: boolean;
|
|
17
|
+
live?: LiveSource | false;
|
|
18
|
+
}
|
|
19
|
+
export interface RunningHttpServer {
|
|
20
|
+
server: Server;
|
|
21
|
+
/** e.g. http://127.0.0.1:8582/mcp */
|
|
22
|
+
url: string;
|
|
23
|
+
close(): Promise<void>;
|
|
24
|
+
}
|
|
25
|
+
export declare function runHttpServer(options: HttpServerOptions): Promise<RunningHttpServer>;
|
|
26
|
+
//# sourceMappingURL=http.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/mcp/http.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,EAAmB,MAAM,EAAkB,MAAM,WAAW,CAAC;AAKzE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAE5C,eAAO,MAAM,QAAQ,SAAS,CAAC;AAG/B,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,sFAAsF;IACtF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,uDAAuD;IACvD,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,gBAAgB,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,UAAU,GAAG,KAAK,CAAC;CAC3B;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,qCAAqC;IACrC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AA+BD,wBAAsB,aAAa,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CA4F1F"}
|