@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":"logs.js","sourceRoot":"","sources":["../../../src/mcp/tools/logs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { HomebridgeClient } from '../homebridge-client.js';
|
|
2
|
+
import type { PluginJob, RegisterTools } from '../types.js';
|
|
3
|
+
/** How often a running job is polled, and for how long a tool call waits for it. */
|
|
4
|
+
export declare const JOB_POLL: {
|
|
5
|
+
intervalMs: number;
|
|
6
|
+
maxWaitMs: number;
|
|
7
|
+
};
|
|
8
|
+
/** Poll a job until it finishes or `maxWaitMs` passes, whichever comes first. */
|
|
9
|
+
export declare function waitForJob(client: HomebridgeClient, jobId: string, maxWaitMs?: number): Promise<PluginJob>;
|
|
10
|
+
export declare const register: RegisterTools;
|
|
11
|
+
//# sourceMappingURL=plugin-jobs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-jobs.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/plugin-jobs.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAG5D,oFAAoF;AACpF,eAAO,MAAM,QAAQ;;;CAA2C,CAAC;AAkBjE,iFAAiF;AACjF,wBAAsB,UAAU,CAAC,MAAM,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,SAAqB,GAAG,OAAO,CAAC,SAAS,CAAC,CAQ5H;AAeD,eAAO,MAAM,QAAQ,EAAE,aAsDtB,CAAC"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { READ, handle, jsonResult } from './helpers.js';
|
|
3
|
+
/** How often a running job is polled, and for how long a tool call waits for it. */
|
|
4
|
+
export const JOB_POLL = { intervalMs: 2000, maxWaitMs: 120_000 };
|
|
5
|
+
/** Keep the end of the npm output; that is where success or the error is. */
|
|
6
|
+
const OUTPUT_TAIL = 4000;
|
|
7
|
+
function summarize(job) {
|
|
8
|
+
const output = job.output ?? '';
|
|
9
|
+
return {
|
|
10
|
+
jobId: job.id,
|
|
11
|
+
action: job.action,
|
|
12
|
+
name: job.name,
|
|
13
|
+
status: job.status,
|
|
14
|
+
startedAt: job.startedAt,
|
|
15
|
+
finishedAt: job.finishedAt,
|
|
16
|
+
output: output.length > OUTPUT_TAIL ? `…${output.slice(-OUTPUT_TAIL)}` : output,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
/** Poll a job until it finishes or `maxWaitMs` passes, whichever comes first. */
|
|
20
|
+
export async function waitForJob(client, jobId, maxWaitMs = JOB_POLL.maxWaitMs) {
|
|
21
|
+
const deadline = Date.now() + maxWaitMs;
|
|
22
|
+
let job = await client.getPluginJob(jobId);
|
|
23
|
+
while (job.status === 'running' && Date.now() < deadline) {
|
|
24
|
+
await new Promise((resolve) => setTimeout(resolve, JOB_POLL.intervalMs));
|
|
25
|
+
job = await client.getPluginJob(jobId);
|
|
26
|
+
}
|
|
27
|
+
return job;
|
|
28
|
+
}
|
|
29
|
+
const name = z
|
|
30
|
+
.string()
|
|
31
|
+
.min(1)
|
|
32
|
+
.regex(/^(@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/, 'must be an npm package name')
|
|
33
|
+
.describe("The npm package name, e.g. 'homebridge-hue' or '@scope/homebridge-plugin'");
|
|
34
|
+
const version = z.string().min(1).optional().describe("Version or dist-tag to install (default 'latest')");
|
|
35
|
+
const wait = z
|
|
36
|
+
.boolean()
|
|
37
|
+
.optional()
|
|
38
|
+
.describe(`Wait for the job to finish (up to ${JOB_POLL.maxWaitMs / 1000}s). Default true; otherwise poll with get_plugin_job.`);
|
|
39
|
+
const WRITE = { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: true };
|
|
40
|
+
export const register = (tool, client) => {
|
|
41
|
+
const run = async (start, shouldWait) => {
|
|
42
|
+
const { jobId } = await start;
|
|
43
|
+
const job = shouldWait === false ? await client.getPluginJob(jobId) : await waitForJob(client, jobId);
|
|
44
|
+
return jsonResult({
|
|
45
|
+
...summarize(job),
|
|
46
|
+
...(job.status === 'running' ? { note: 'Still running; call get_plugin_job with this jobId to follow it.' } : {}),
|
|
47
|
+
...(job.status === 'succeeded' ? { note: 'Restart Homebridge (or the plugin\'s child bridge) to load the change.' } : {}),
|
|
48
|
+
});
|
|
49
|
+
};
|
|
50
|
+
tool('install_plugin', {
|
|
51
|
+
title: 'Install plugin',
|
|
52
|
+
description: 'Install a Homebridge plugin from npm. Runs as a background job on the Homebridge UI; returns the job status and npm output.',
|
|
53
|
+
inputSchema: { name, version, wait },
|
|
54
|
+
annotations: WRITE,
|
|
55
|
+
}, handle('installing plugin', async ({ name, version, wait }) => run(client.installPlugin(name, version), wait)));
|
|
56
|
+
tool('update_plugin', {
|
|
57
|
+
title: 'Update plugin',
|
|
58
|
+
description: 'Update an installed Homebridge plugin to the latest (or a given) version. Check get_plugin_changelog for breaking changes first.',
|
|
59
|
+
inputSchema: { name, version, wait },
|
|
60
|
+
annotations: WRITE,
|
|
61
|
+
}, handle('updating plugin', async ({ name, version, wait }) => run(client.updatePlugin(name, version), wait)));
|
|
62
|
+
tool('uninstall_plugin', {
|
|
63
|
+
title: 'Uninstall plugin',
|
|
64
|
+
description: 'Uninstall a Homebridge plugin. Its config.json blocks are left in place.',
|
|
65
|
+
inputSchema: { name, wait },
|
|
66
|
+
annotations: WRITE,
|
|
67
|
+
}, handle('uninstalling plugin', async ({ name, wait }) => run(client.uninstallPlugin(name), wait)));
|
|
68
|
+
tool('get_plugin_job', {
|
|
69
|
+
title: 'Plugin job status',
|
|
70
|
+
description: 'Get the status and npm output of a plugin install, update or uninstall job.',
|
|
71
|
+
inputSchema: { jobId: z.string().min(1).describe('The jobId returned by install_plugin, update_plugin or uninstall_plugin') },
|
|
72
|
+
annotations: READ,
|
|
73
|
+
}, handle('getting plugin job', async ({ jobId }) => jsonResult(summarize(await client.getPluginJob(jobId)))));
|
|
74
|
+
};
|
|
75
|
+
//# sourceMappingURL=plugin-jobs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-jobs.js","sourceRoot":"","sources":["../../../src/mcp/tools/plugin-jobs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugins.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/plugins.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AA0BjD,eAAO,MAAM,QAAQ,EAAE,aAgFtB,CAAC"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { READ, READ_REGISTRY, handle, jsonResult, pick, textResult } from './helpers.js';
|
|
3
|
+
const INSTALLED_FIELDS = [
|
|
4
|
+
'name',
|
|
5
|
+
'displayName',
|
|
6
|
+
'installedVersion',
|
|
7
|
+
'latestVersion',
|
|
8
|
+
'updateAvailable',
|
|
9
|
+
'verifiedPlugin',
|
|
10
|
+
'disabled',
|
|
11
|
+
];
|
|
12
|
+
const SEARCH_FIELDS = [
|
|
13
|
+
'name',
|
|
14
|
+
'displayName',
|
|
15
|
+
'description',
|
|
16
|
+
'latestVersion',
|
|
17
|
+
'lastUpdated',
|
|
18
|
+
'verifiedPlugin',
|
|
19
|
+
'installedVersion',
|
|
20
|
+
];
|
|
21
|
+
const pluginName = z.string().min(1).describe("The npm package name of the plugin (e.g. 'homebridge-hue')");
|
|
22
|
+
const verbose = z.boolean().optional().describe('Return every field the API provides (large). Default false.');
|
|
23
|
+
export const register = (tool, client) => {
|
|
24
|
+
tool('list_plugins', {
|
|
25
|
+
title: 'List installed plugins',
|
|
26
|
+
description: 'List all currently installed Homebridge plugins with their versions and update status. ' +
|
|
27
|
+
'Pass verbose=true for every field (links, engines, install path, keywords, ...).',
|
|
28
|
+
inputSchema: { verbose },
|
|
29
|
+
annotations: READ,
|
|
30
|
+
}, handle('listing plugins', async ({ verbose }) => {
|
|
31
|
+
const plugins = await client.getPlugins();
|
|
32
|
+
return jsonResult(verbose ? plugins : plugins.map((p) => pick(p, INSTALLED_FIELDS)));
|
|
33
|
+
}));
|
|
34
|
+
tool('search_plugins', {
|
|
35
|
+
title: 'Search plugins',
|
|
36
|
+
description: 'Search the npm registry for Homebridge plugins matching a query. Pass verbose=true for every field.',
|
|
37
|
+
inputSchema: {
|
|
38
|
+
query: z.string().min(1).describe("Search query (e.g. 'hue', 'camera', 'thermostat')"),
|
|
39
|
+
verbose,
|
|
40
|
+
},
|
|
41
|
+
annotations: READ_REGISTRY,
|
|
42
|
+
}, handle('searching plugins', async ({ query, verbose }) => {
|
|
43
|
+
const results = await client.searchPlugins(query);
|
|
44
|
+
return jsonResult(verbose ? results : results.map((p) => pick(p, SEARCH_FIELDS)));
|
|
45
|
+
}));
|
|
46
|
+
tool('lookup_plugin', {
|
|
47
|
+
title: 'Look up plugin',
|
|
48
|
+
description: 'Get detailed information about a specific Homebridge plugin from the npm registry.',
|
|
49
|
+
inputSchema: { pluginName },
|
|
50
|
+
annotations: READ_REGISTRY,
|
|
51
|
+
}, handle('looking up plugin', async ({ pluginName }) => jsonResult(await client.lookupPlugin(pluginName))));
|
|
52
|
+
tool('get_plugin_versions', {
|
|
53
|
+
title: 'Plugin versions',
|
|
54
|
+
description: 'Get available versions and dist-tags for a specific Homebridge plugin.',
|
|
55
|
+
inputSchema: { pluginName },
|
|
56
|
+
annotations: READ_REGISTRY,
|
|
57
|
+
}, handle('getting plugin versions', async ({ pluginName }) => jsonResult(await client.getPluginVersions(pluginName))));
|
|
58
|
+
tool('get_plugin_config_schema', {
|
|
59
|
+
title: 'Plugin config schema',
|
|
60
|
+
description: 'Get the config.schema.json for a plugin, which describes how to configure it in Homebridge.',
|
|
61
|
+
inputSchema: { pluginName },
|
|
62
|
+
annotations: READ,
|
|
63
|
+
}, handle('getting plugin config schema', async ({ pluginName }) => jsonResult(await client.getPluginConfigSchema(pluginName))));
|
|
64
|
+
tool('get_plugin_changelog', {
|
|
65
|
+
title: 'Plugin changelog',
|
|
66
|
+
description: 'Get the CHANGELOG.md content for an installed Homebridge plugin.',
|
|
67
|
+
inputSchema: { pluginName },
|
|
68
|
+
annotations: READ,
|
|
69
|
+
}, handle('getting plugin changelog', async ({ pluginName }) => {
|
|
70
|
+
const changelog = await client.getPluginChangelog(pluginName);
|
|
71
|
+
return typeof changelog === 'string' ? textResult(changelog) : jsonResult(changelog);
|
|
72
|
+
}));
|
|
73
|
+
};
|
|
74
|
+
//# sourceMappingURL=plugins.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugins.js","sourceRoot":"","sources":["../../../src/mcp/tools/plugins.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAEzF,MAAM,gBAAgB,GAAG;IACvB,MAAM;IACN,aAAa;IACb,kBAAkB;IAClB,eAAe;IACf,iBAAiB;IACjB,gBAAgB;IAChB,UAAU;CACF,CAAC;AAEX,MAAM,aAAa,GAAG;IACpB,MAAM;IACN,aAAa;IACb,aAAa;IACb,eAAe;IACf,aAAa;IACb,gBAAgB;IAChB,kBAAkB;CACV,CAAC;AAEX,MAAM,UAAU,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,4DAA4D,CAAC,CAAC;AAC5G,MAAM,OAAO,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,6DAA6D,CAAC,CAAC;AAE/G,MAAM,CAAC,MAAM,QAAQ,GAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE;IACtD,IAAI,CACF,cAAc,EACd;QACE,KAAK,EAAE,wBAAwB;QAC/B,WAAW,EACT,yFAAyF;YACzF,kFAAkF;QACpF,WAAW,EAAE,EAAE,OAAO,EAAE;QACxB,WAAW,EAAE,IAAI;KAClB,EACD,MAAM,CAAC,iBAAiB,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE;QAC9C,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,UAAU,EAAE,CAAC;QAC1C,OAAO,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAC;IACvF,CAAC,CAAC,CACH,CAAC;IAEF,IAAI,CACF,gBAAgB,EAChB;QACE,KAAK,EAAE,gBAAgB;QACvB,WAAW,EAAE,qGAAqG;QAClH,WAAW,EAAE;YACX,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,mDAAmD,CAAC;YACtF,OAAO;SACR;QACD,WAAW,EAAE,aAAa;KAC3B,EACD,MAAM,CAAC,mBAAmB,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE;QACvD,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAClD,OAAO,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC;IACpF,CAAC,CAAC,CACH,CAAC;IAEF,IAAI,CACF,eAAe,EACf;QACE,KAAK,EAAE,gBAAgB;QACvB,WAAW,EAAE,oFAAoF;QACjG,WAAW,EAAE,EAAE,UAAU,EAAE;QAC3B,WAAW,EAAE,aAAa;KAC3B,EACD,MAAM,CAAC,mBAAmB,EAAE,KAAK,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,UAAU,CAAC,MAAM,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,CACzG,CAAC;IAEF,IAAI,CACF,qBAAqB,EACrB;QACE,KAAK,EAAE,iBAAiB;QACxB,WAAW,EAAE,wEAAwE;QACrF,WAAW,EAAE,EAAE,UAAU,EAAE;QAC3B,WAAW,EAAE,aAAa;KAC3B,EACD,MAAM,CAAC,yBAAyB,EAAE,KAAK,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,UAAU,CAAC,MAAM,MAAM,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC,CAAC,CACpH,CAAC;IAEF,IAAI,CACF,0BAA0B,EAC1B;QACE,KAAK,EAAE,sBAAsB;QAC7B,WAAW,EAAE,6FAA6F;QAC1G,WAAW,EAAE,EAAE,UAAU,EAAE;QAC3B,WAAW,EAAE,IAAI;KAClB,EACD,MAAM,CAAC,8BAA8B,EAAE,KAAK,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,UAAU,CAAC,MAAM,MAAM,CAAC,qBAAqB,CAAC,UAAU,CAAC,CAAC,CAAC,CAC7H,CAAC;IAEF,IAAI,CACF,sBAAsB,EACtB;QACE,KAAK,EAAE,kBAAkB;QACzB,WAAW,EAAE,kEAAkE;QAC/E,WAAW,EAAE,EAAE,UAAU,EAAE;QAC3B,WAAW,EAAE,IAAI;KAClB,EACD,MAAM,CAAC,0BAA0B,EAAE,KAAK,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE;QAC1D,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,UAAU,CAAC,CAAC;QAC9D,OAAO,OAAO,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IACvF,CAAC,CAAC,CACH,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/server.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAKjD,eAAO,MAAM,QAAQ,EAAE,aAqGtB,CAAC"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { READ, handle, jsonResult, pick, textResult } from './helpers.js';
|
|
3
|
+
const CACHED_ACCESSORY_FIELDS = ['UUID', 'displayName', 'plugin', 'platform', 'category'];
|
|
4
|
+
export const register = (tool, client) => {
|
|
5
|
+
tool('get_homebridge_status', {
|
|
6
|
+
title: 'Homebridge status',
|
|
7
|
+
description: 'Check if Homebridge is running and get its current status (up/down, version, plugins status).',
|
|
8
|
+
annotations: READ,
|
|
9
|
+
}, handle('getting Homebridge status', async () => jsonResult(await client.getHomebridgeStatus())));
|
|
10
|
+
tool('get_server_status', {
|
|
11
|
+
title: 'Server information',
|
|
12
|
+
description: 'Get Homebridge server information including version, Node.js version, uptime, OS details, and Homebridge instance ID.',
|
|
13
|
+
annotations: READ,
|
|
14
|
+
}, handle('getting server info', async () => jsonResult(await client.getServerInformation())));
|
|
15
|
+
tool('restart_homebridge', {
|
|
16
|
+
title: 'Restart Homebridge',
|
|
17
|
+
description: 'Restart the Homebridge service. This will temporarily make all accessories unavailable.',
|
|
18
|
+
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: false },
|
|
19
|
+
}, handle('restarting Homebridge', async () => {
|
|
20
|
+
const result = await client.restartServer();
|
|
21
|
+
return result ? jsonResult(result) : textResult('Homebridge restart initiated successfully.');
|
|
22
|
+
}));
|
|
23
|
+
tool('get_pairing_info', {
|
|
24
|
+
title: 'HomeKit pairing info',
|
|
25
|
+
description: 'Get the HomeKit pairing information (setup code, QR code URL) for this Homebridge instance. ' +
|
|
26
|
+
'The setup code lets anyone on the network pair with the bridge, so only fetch it when the user asks to pair a device.',
|
|
27
|
+
annotations: READ,
|
|
28
|
+
}, handle('getting pairing info', async () => jsonResult(await client.getPairingInfo())));
|
|
29
|
+
tool('get_cached_accessories', {
|
|
30
|
+
title: 'List cached accessories',
|
|
31
|
+
description: 'List cached accessories stored by Homebridge (UUID, name, plugin, platform, category and cacheFile). These persist across restarts. ' +
|
|
32
|
+
'Pass verbose=true for the full cached objects including services and context.',
|
|
33
|
+
inputSchema: {
|
|
34
|
+
verbose: z.boolean().optional().describe('Return the full cached accessory objects (large). Default false.'),
|
|
35
|
+
},
|
|
36
|
+
annotations: READ,
|
|
37
|
+
}, handle('getting cached accessories', async ({ verbose }) => {
|
|
38
|
+
const cached = await client.getCachedAccessories();
|
|
39
|
+
if (verbose) {
|
|
40
|
+
return jsonResult(cached);
|
|
41
|
+
}
|
|
42
|
+
return jsonResult(cached.map((acc) => ({ ...pick(acc, CACHED_ACCESSORY_FIELDS), cacheFile: acc.$cacheFile })));
|
|
43
|
+
}));
|
|
44
|
+
tool('remove_cached_accessory', {
|
|
45
|
+
title: 'Remove cached accessory',
|
|
46
|
+
description: 'Remove a specific cached accessory by its UUID. Useful for cleaning up stale accessories. ' +
|
|
47
|
+
'Pass the cacheFile reported by get_cached_accessories for accessories that belong to a child bridge.',
|
|
48
|
+
inputSchema: {
|
|
49
|
+
uuid: z.string().min(1).describe('The UUID of the cached accessory to remove'),
|
|
50
|
+
cacheFile: z
|
|
51
|
+
.string()
|
|
52
|
+
.optional()
|
|
53
|
+
.describe('The cacheFile from get_cached_accessories. Omit for accessories on the main bridge.'),
|
|
54
|
+
},
|
|
55
|
+
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false },
|
|
56
|
+
}, handle('removing cached accessory', async ({ uuid, cacheFile }) => {
|
|
57
|
+
await client.removeCachedAccessory(uuid, cacheFile);
|
|
58
|
+
return textResult(`Cached accessory ${uuid} removed successfully.`);
|
|
59
|
+
}));
|
|
60
|
+
tool('reset_cached_accessories', {
|
|
61
|
+
title: 'Reset all cached accessories',
|
|
62
|
+
description: 'Reset ALL cached accessories. WARNING: This removes all cached accessories and requires a Homebridge restart.',
|
|
63
|
+
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false },
|
|
64
|
+
}, handle('resetting cached accessories', async () => {
|
|
65
|
+
await client.resetCachedAccessories();
|
|
66
|
+
return textResult('All cached accessories have been reset. A Homebridge restart may be required.');
|
|
67
|
+
}));
|
|
68
|
+
};
|
|
69
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../../src/mcp/tools/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"system.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/system.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGjD,eAAO,MAAM,QAAQ,EAAE,aAUtB,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { READ, handle, jsonResult } from './helpers.js';
|
|
2
|
+
export const register = (tool, client) => {
|
|
3
|
+
tool('get_system_info', {
|
|
4
|
+
title: 'Host system info',
|
|
5
|
+
description: 'Get system information for the machine running Homebridge (CPU, memory, OS, network interfaces, uptime).',
|
|
6
|
+
annotations: READ,
|
|
7
|
+
}, handle('getting system info', async () => jsonResult(await client.getSystemInfo())));
|
|
8
|
+
};
|
|
9
|
+
//# sourceMappingURL=system.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"system.js","sourceRoot":"","sources":["../../../src/mcp/tools/system.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAExD,MAAM,CAAC,MAAM,QAAQ,GAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE;IACtD,IAAI,CACF,iBAAiB,EACjB;QACE,KAAK,EAAE,kBAAkB;QACzB,WAAW,EAAE,0GAA0G;QACvH,WAAW,EAAE,IAAI;KAClB,EACD,MAAM,CAAC,qBAAqB,EAAE,KAAK,IAAI,EAAE,CAAC,UAAU,CAAC,MAAM,MAAM,CAAC,aAAa,EAAE,CAAC,CAAC,CACpF,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type { HomebridgeClient } from './homebridge-client.js';
|
|
2
|
+
import type { ToolRegistrar } from './tools/helpers.js';
|
|
3
|
+
/**
|
|
4
|
+
* Signature for tool registration functions.
|
|
5
|
+
* Each tools/*.ts file exports a `register` function matching this type.
|
|
6
|
+
*/
|
|
7
|
+
export type RegisterTools = (tool: ToolRegistrar, client: HomebridgeClient) => void;
|
|
8
|
+
export interface Accessory {
|
|
9
|
+
uniqueId: string;
|
|
10
|
+
serviceName: string;
|
|
11
|
+
type: string;
|
|
12
|
+
accessoryInformation?: {
|
|
13
|
+
Manufacturer?: string;
|
|
14
|
+
Model?: string;
|
|
15
|
+
Name?: string;
|
|
16
|
+
};
|
|
17
|
+
serviceCharacteristics?: CharacteristicInfo[];
|
|
18
|
+
values?: Record<string, unknown>;
|
|
19
|
+
}
|
|
20
|
+
export interface Room {
|
|
21
|
+
name: string;
|
|
22
|
+
services: Array<{
|
|
23
|
+
uniqueId: string;
|
|
24
|
+
customName?: string;
|
|
25
|
+
}>;
|
|
26
|
+
}
|
|
27
|
+
export interface CachedAccessory {
|
|
28
|
+
UUID: string;
|
|
29
|
+
displayName?: string;
|
|
30
|
+
plugin?: string;
|
|
31
|
+
platform?: string;
|
|
32
|
+
category?: number;
|
|
33
|
+
/** Added by the UI: which cache file (main bridge or a child bridge) holds this accessory. */
|
|
34
|
+
$cacheFile?: string;
|
|
35
|
+
[key: string]: unknown;
|
|
36
|
+
}
|
|
37
|
+
export type Plugin = Record<string, unknown> & {
|
|
38
|
+
name: string;
|
|
39
|
+
};
|
|
40
|
+
/** Characteristic metadata as the Homebridge UI reports it. */
|
|
41
|
+
export interface CharacteristicInfo {
|
|
42
|
+
type: string;
|
|
43
|
+
value: unknown;
|
|
44
|
+
format?: string;
|
|
45
|
+
canWrite?: boolean;
|
|
46
|
+
minValue?: number;
|
|
47
|
+
maxValue?: number;
|
|
48
|
+
minStep?: number;
|
|
49
|
+
maxLen?: number;
|
|
50
|
+
validValues?: number[];
|
|
51
|
+
description?: string;
|
|
52
|
+
unit?: string;
|
|
53
|
+
}
|
|
54
|
+
export interface PluginJob {
|
|
55
|
+
id: string;
|
|
56
|
+
action: 'install' | 'update' | 'uninstall';
|
|
57
|
+
name: string;
|
|
58
|
+
status: 'running' | 'succeeded' | 'failed';
|
|
59
|
+
output: string;
|
|
60
|
+
startedAt: string;
|
|
61
|
+
finishedAt?: string;
|
|
62
|
+
}
|
|
63
|
+
export interface ChildBridge {
|
|
64
|
+
username: string;
|
|
65
|
+
name: string;
|
|
66
|
+
plugin: string;
|
|
67
|
+
identifier?: string;
|
|
68
|
+
status: 'pending' | 'ok' | 'down' | string;
|
|
69
|
+
paired?: boolean | null;
|
|
70
|
+
pid?: number;
|
|
71
|
+
port?: number;
|
|
72
|
+
manuallyStopped?: boolean;
|
|
73
|
+
[key: string]: unknown;
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/mcp/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/mcp/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { PLATFORM_NAME, PLUGIN_NAME, registerAiRoutes, testAiConnection } from '@mp-consulting/homebridge-ai-core/plugin';
|
|
2
|
+
export type { AiRoutesOptions, ConnectionTest, PluginUiServer } from '@mp-consulting/homebridge-ai-core/plugin';
|
|
3
|
+
export { mcpClientSnippets } from './snippets.js';
|
|
4
|
+
export type { McpClientSnippets, SnippetOptions } from './snippets.js';
|
|
5
|
+
export { AiKitPlatform } from './platform.js';
|
|
6
|
+
export type { PlatformApi, PlatformLogger } from './platform.js';
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/plugin/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,0CAA0C,CAAC;AAC1H,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,0CAA0C,CAAC;AAChH,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,YAAY,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,YAAY,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// The shared plugin-UI routes live in @mp-consulting/homebridge-ai-core; re-exported for backward compatibility.
|
|
2
|
+
export { PLATFORM_NAME, PLUGIN_NAME, registerAiRoutes, testAiConnection } from '@mp-consulting/homebridge-ai-core/plugin';
|
|
3
|
+
export { mcpClientSnippets } from './snippets.js';
|
|
4
|
+
export { AiKitPlatform } from './platform.js';
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/plugin/index.ts"],"names":[],"mappings":"AAAA,iHAAiH;AACjH,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,0CAA0C,CAAC;AAE1H,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAElD,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `HomebridgeAiKit` platform. It exposes no accessories: it reports the
|
|
3
|
+
* Assistant's configuration and, when enabled, serves MCP over HTTP so
|
|
4
|
+
* outside clients (Claude Desktop, Claude Code, Cursor) can reach Homebridge.
|
|
5
|
+
*/
|
|
6
|
+
import type { AiConfig } from '@mp-consulting/homebridge-ai-core';
|
|
7
|
+
/** The slice of Homebridge's logger, config and API the platform needs (no runtime dependency on homebridge). */
|
|
8
|
+
export interface PlatformLogger {
|
|
9
|
+
info(message: string, ...params: unknown[]): void;
|
|
10
|
+
warn(message: string, ...params: unknown[]): void;
|
|
11
|
+
error(message: string, ...params: unknown[]): void;
|
|
12
|
+
}
|
|
13
|
+
export interface PlatformApi {
|
|
14
|
+
on(event: 'didFinishLaunching' | 'shutdown', listener: () => void): unknown;
|
|
15
|
+
}
|
|
16
|
+
export declare class AiKitPlatform {
|
|
17
|
+
private readonly log;
|
|
18
|
+
readonly config: AiConfig | null;
|
|
19
|
+
private http;
|
|
20
|
+
/** Settles once startup work (the HTTP server) is done. */
|
|
21
|
+
ready: Promise<void>;
|
|
22
|
+
constructor(log: PlatformLogger, rawConfig: unknown, api: PlatformApi);
|
|
23
|
+
/** Homebridge calls this for cached accessories; this platform has none. */
|
|
24
|
+
configureAccessory(): void;
|
|
25
|
+
private logStatus;
|
|
26
|
+
private startHttp;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=platform.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"platform.d.ts","sourceRoot":"","sources":["../../src/plugin/platform.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mCAAmC,CAAC;AAMlE,iHAAiH;AACjH,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAClD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAClD,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;CACpD;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,CAAC,KAAK,EAAE,oBAAoB,GAAG,UAAU,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC;CAC7E;AAED,qBAAa,aAAa;IAOtB,OAAO,CAAC,QAAQ,CAAC,GAAG;IANtB,QAAQ,CAAC,MAAM,EAAE,QAAQ,GAAG,IAAI,CAAQ;IACxC,OAAO,CAAC,IAAI,CAAgC;IAC5C,2DAA2D;IAC3D,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,CAAqB;gBAGtB,GAAG,EAAE,cAAc,EACpC,SAAS,EAAE,OAAO,EAClB,GAAG,EAAE,WAAW;IAiBlB,4EAA4E;IAC5E,kBAAkB,IAAI,IAAI;IAE1B,OAAO,CAAC,SAAS;YAcH,SAAS;CAyBxB"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `HomebridgeAiKit` platform. It exposes no accessories: it reports the
|
|
3
|
+
* Assistant's configuration and, when enabled, serves MCP over HTTP so
|
|
4
|
+
* outside clients (Claude Desktop, Claude Code, Cursor) can reach Homebridge.
|
|
5
|
+
*/
|
|
6
|
+
import { DEFAULT_HOMEBRIDGE_URL, createProvider, resolveAiConfig } from '@mp-consulting/homebridge-ai-core';
|
|
7
|
+
import { HomebridgeClient } from '../mcp/homebridge-client.js';
|
|
8
|
+
import { runHttpServer } from '../mcp/http.js';
|
|
9
|
+
export class AiKitPlatform {
|
|
10
|
+
log;
|
|
11
|
+
config = null;
|
|
12
|
+
http;
|
|
13
|
+
/** Settles once startup work (the HTTP server) is done. */
|
|
14
|
+
ready = Promise.resolve();
|
|
15
|
+
constructor(log, rawConfig, api) {
|
|
16
|
+
this.log = log;
|
|
17
|
+
try {
|
|
18
|
+
this.config = resolveAiConfig(rawConfig);
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
log.error(`Invalid configuration: ${error.message}`);
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
this.logStatus(this.config);
|
|
25
|
+
api.on('didFinishLaunching', () => {
|
|
26
|
+
this.ready = this.startHttp(this.config);
|
|
27
|
+
});
|
|
28
|
+
api.on('shutdown', () => {
|
|
29
|
+
void this.http?.close();
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
/** Homebridge calls this for cached accessories; this platform has none. */
|
|
33
|
+
configureAccessory() { }
|
|
34
|
+
logStatus(config) {
|
|
35
|
+
if (!config.enabled) {
|
|
36
|
+
this.log.info('Assistant disabled.');
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
try {
|
|
40
|
+
const provider = createProvider(config);
|
|
41
|
+
const { tools, contextTokens } = provider.capabilities;
|
|
42
|
+
this.log.info(`Assistant ready: ${config.provider} / ${config.model} (${tools ? 'tools' : 'no tools'}, ${contextTokens} token context).`);
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
this.log.warn(`Assistant not ready: ${error.message}`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
async startHttp(config) {
|
|
49
|
+
const http = config.mcp.http;
|
|
50
|
+
if (!http.enabled) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const token = http.token || process.env.HOMEBRIDGE_AI_MCP_TOKEN;
|
|
54
|
+
if (!token) {
|
|
55
|
+
this.log.error('MCP over HTTP is enabled but has no token. Set one in the AI Kit settings.');
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
let client;
|
|
59
|
+
try {
|
|
60
|
+
const url = http.homebridgeUrl || process.env.HOMEBRIDGE_URL || DEFAULT_HOMEBRIDGE_URL;
|
|
61
|
+
client = new HomebridgeClient(http.homebridgeToken ? { url, token: http.homebridgeToken } : { url });
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
this.log.error(`MCP over HTTP not started: ${error.message}. Set a Homebridge API token in the AI Kit settings.`);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
try {
|
|
68
|
+
this.http = await runHttpServer({ host: http.host, port: http.port, token, client });
|
|
69
|
+
this.log.info(`MCP server listening at ${this.http.url}`);
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
this.log.error(`MCP over HTTP not started: ${error.message}`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=platform.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"platform.js","sourceRoot":"","sources":["../../src/plugin/platform.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/** Config snippets that point outside MCP clients at this Homebridge. */
|
|
2
|
+
export interface SnippetOptions {
|
|
3
|
+
/** Homebridge UI URL, e.g. http://192.168.1.10:8581. */
|
|
4
|
+
homebridgeUrl: string;
|
|
5
|
+
/** The HTTP MCP server, when enabled in the plugin. */
|
|
6
|
+
http?: {
|
|
7
|
+
host: string;
|
|
8
|
+
port: number;
|
|
9
|
+
token?: string;
|
|
10
|
+
};
|
|
11
|
+
/** Put the real token in the snippet instead of a placeholder. */
|
|
12
|
+
includeToken?: boolean;
|
|
13
|
+
}
|
|
14
|
+
export interface McpClientSnippets {
|
|
15
|
+
/** `claude_desktop_config.json` → mcpServers entry. */
|
|
16
|
+
claudeDesktop: string;
|
|
17
|
+
/** A `claude mcp add` command line. */
|
|
18
|
+
claudeCode: string;
|
|
19
|
+
/** `.cursor/mcp.json` → mcpServers entry. */
|
|
20
|
+
cursor: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Snippets for Claude Desktop, Claude Code and Cursor. With `http` they use the
|
|
24
|
+
* plugin's Streamable HTTP server; otherwise they launch the stdio server with npx.
|
|
25
|
+
*/
|
|
26
|
+
export declare function mcpClientSnippets(options: SnippetOptions): McpClientSnippets;
|
|
27
|
+
//# sourceMappingURL=snippets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snippets.d.ts","sourceRoot":"","sources":["../../src/plugin/snippets.ts"],"names":[],"mappings":"AAAA,yEAAyE;AAEzE,MAAM,WAAW,cAAc;IAC7B,wDAAwD;IACxD,aAAa,EAAE,MAAM,CAAC;IACtB,uDAAuD;IACvD,IAAI,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACtD,kEAAkE;IAClE,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,uDAAuD;IACvD,aAAa,EAAE,MAAM,CAAC;IACtB,uCAAuC;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,6CAA6C;IAC7C,MAAM,EAAE,MAAM,CAAC;CAChB;AASD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,cAAc,GAAG,iBAAiB,CA2B5E"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/** Config snippets that point outside MCP clients at this Homebridge. */
|
|
2
|
+
const TOKEN_PLACEHOLDER = '<your MCP token>';
|
|
3
|
+
const PACKAGE = '@mp-consulting/homebridge-ai-kit';
|
|
4
|
+
function shellQuote(s) {
|
|
5
|
+
return /^[\w@%+=:,./-]+$/.test(s) ? s : `'${s.replace(/'/g, '\'\\\'\'')}'`;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Snippets for Claude Desktop, Claude Code and Cursor. With `http` they use the
|
|
9
|
+
* plugin's Streamable HTTP server; otherwise they launch the stdio server with npx.
|
|
10
|
+
*/
|
|
11
|
+
export function mcpClientSnippets(options) {
|
|
12
|
+
if (options.http) {
|
|
13
|
+
const host = ['0.0.0.0', '::', ''].includes(options.http.host) ? '127.0.0.1' : options.http.host;
|
|
14
|
+
const url = `http://${host.includes(':') ? `[${host}]` : host}:${options.http.port}/mcp`;
|
|
15
|
+
const token = options.includeToken && options.http.token ? options.http.token : TOKEN_PLACEHOLDER;
|
|
16
|
+
const headers = { Authorization: `Bearer ${token}` };
|
|
17
|
+
return {
|
|
18
|
+
// Claude Desktop only speaks stdio to local servers; mcp-remote bridges to HTTP.
|
|
19
|
+
claudeDesktop: JSON.stringify({ mcpServers: { homebridge: { command: 'npx', args: ['-y', 'mcp-remote', url, '--header', `Authorization:Bearer ${token}`] } } }, null, 2),
|
|
20
|
+
claudeCode: `claude mcp add --transport http homebridge ${url} --header ${shellQuote(`Authorization: Bearer ${token}`)}`,
|
|
21
|
+
cursor: JSON.stringify({ mcpServers: { homebridge: { url, headers } } }, null, 2),
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
const env = { HOMEBRIDGE_URL: options.homebridgeUrl, HOMEBRIDGE_TOKEN: '<a Homebridge API token>' };
|
|
25
|
+
const stdio = { command: 'npx', args: ['-y', PACKAGE, 'mcp'], env };
|
|
26
|
+
return {
|
|
27
|
+
claudeDesktop: JSON.stringify({ mcpServers: { homebridge: stdio } }, null, 2),
|
|
28
|
+
claudeCode: `claude mcp add homebridge -e HOMEBRIDGE_URL=${shellQuote(env.HOMEBRIDGE_URL)} -e ${shellQuote(`HOMEBRIDGE_TOKEN=${env.HOMEBRIDGE_TOKEN}`)} ` +
|
|
29
|
+
`-- npx -y ${PACKAGE} mcp`,
|
|
30
|
+
cursor: JSON.stringify({ mcpServers: { homebridge: stdio } }, null, 2),
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=snippets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snippets.js","sourceRoot":"","sources":["../../src/plugin/snippets.ts"],"names":[],"mappings":"AAAA,yEAAyE;AAoBzE,MAAM,iBAAiB,GAAG,kBAAkB,CAAC;AAC7C,MAAM,OAAO,GAAG,kCAAkC,CAAC;AAEnD,SAAS,UAAU,CAAC,CAAS;IAC3B,OAAO,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,UAAU,CAAC,GAAG,CAAC;AAC7E,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAuB;IACvD,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,MAAM,IAAI,GAAG,CAAC,SAAS,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;QACjG,MAAM,GAAG,GAAG,UAAU,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC;QACzF,MAAM,KAAK,GAAG,OAAO,CAAC,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,iBAAiB,CAAC;QAClG,MAAM,OAAO,GAAG,EAAE,aAAa,EAAE,UAAU,KAAK,EAAE,EAAE,CAAC;QACrD,OAAO;YACL,iFAAiF;YACjF,aAAa,EAAE,IAAI,CAAC,SAAS,CAC3B,EAAE,UAAU,EAAE,EAAE,UAAU,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,YAAY,EAAE,GAAG,EAAE,UAAU,EAAE,wBAAwB,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,EAChI,IAAI,EACJ,CAAC,CACF;YACD,UAAU,EAAE,8CAA8C,GAAG,aAAa,UAAU,CAAC,yBAAyB,KAAK,EAAE,CAAC,EAAE;YACxH,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,UAAU,EAAE,EAAE,UAAU,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;SAClF,CAAC;IACJ,CAAC;IAED,MAAM,GAAG,GAAG,EAAE,cAAc,EAAE,OAAO,CAAC,aAAa,EAAE,gBAAgB,EAAE,0BAA0B,EAAE,CAAC;IACpG,MAAM,KAAK,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,GAAG,EAAE,CAAC;IACpE,OAAO;QACL,aAAa,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,UAAU,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7E,UAAU,EACR,+CAA+C,UAAU,CAAC,GAAG,CAAC,cAAc,CAAC,OAAO,UAAU,CAAC,oBAAoB,GAAG,CAAC,gBAAgB,EAAE,CAAC,GAAG;YAC7I,aAAa,OAAO,MAAM;QAC5B,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,UAAU,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;KACvE,CAAC;AACJ,CAAC"}
|