viyv-browser-mcp 0.7.1 → 0.7.3
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/dist/index.js +165 -67
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -88,6 +88,57 @@ var MCP_SERVER = {
|
|
|
88
88
|
SOCKET_PATH_TEMPLATE: "/tmp/viyv-browser-{pid}.sock"
|
|
89
89
|
};
|
|
90
90
|
|
|
91
|
+
// src/native-host-updater.ts
|
|
92
|
+
import { chmodSync, copyFileSync, existsSync, mkdirSync, renameSync, unlinkSync } from "fs";
|
|
93
|
+
import { homedir } from "os";
|
|
94
|
+
import { resolve } from "path";
|
|
95
|
+
import { fileURLToPath } from "url";
|
|
96
|
+
var NATIVE_HOST_DIR = resolve(homedir(), ".viyv-browser", "native-host");
|
|
97
|
+
function getSourceBinaryPath() {
|
|
98
|
+
return fileURLToPath(import.meta.url);
|
|
99
|
+
}
|
|
100
|
+
function getNativeHostBinaryPath() {
|
|
101
|
+
return resolve(NATIVE_HOST_DIR, "index.js");
|
|
102
|
+
}
|
|
103
|
+
function isNativeHostDeployed() {
|
|
104
|
+
return existsSync(getNativeHostBinaryPath());
|
|
105
|
+
}
|
|
106
|
+
function syncNativeHostBinary() {
|
|
107
|
+
const source = getSourceBinaryPath();
|
|
108
|
+
if (!existsSync(source)) {
|
|
109
|
+
throw new Error(`Source binary not found: ${source}`);
|
|
110
|
+
}
|
|
111
|
+
mkdirSync(NATIVE_HOST_DIR, { recursive: true });
|
|
112
|
+
const target = getNativeHostBinaryPath();
|
|
113
|
+
const tmp = resolve(NATIVE_HOST_DIR, `index.js.tmp.${process.pid}`);
|
|
114
|
+
try {
|
|
115
|
+
copyFileSync(source, tmp);
|
|
116
|
+
chmodSync(tmp, 493);
|
|
117
|
+
renameSync(tmp, target);
|
|
118
|
+
} catch (err) {
|
|
119
|
+
try {
|
|
120
|
+
unlinkSync(tmp);
|
|
121
|
+
} catch {
|
|
122
|
+
}
|
|
123
|
+
throw err;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
function shouldUpdateBridge(bridgeVersion) {
|
|
127
|
+
return compareSemver("0.7.3", bridgeVersion) > 0;
|
|
128
|
+
}
|
|
129
|
+
function getPackageVersion() {
|
|
130
|
+
return "0.7.3";
|
|
131
|
+
}
|
|
132
|
+
function compareSemver(a, b) {
|
|
133
|
+
const pa = a.split(".").map(Number);
|
|
134
|
+
const pb = b.split(".").map(Number);
|
|
135
|
+
for (let i = 0; i < 3; i++) {
|
|
136
|
+
const diff = (pa[i] ?? 0) - (pb[i] ?? 0);
|
|
137
|
+
if (diff !== 0) return diff;
|
|
138
|
+
}
|
|
139
|
+
return 0;
|
|
140
|
+
}
|
|
141
|
+
|
|
91
142
|
// src/native-host/bridge-relay.ts
|
|
92
143
|
import { createConnection } from "net";
|
|
93
144
|
|
|
@@ -382,6 +433,7 @@ function startBridge(options) {
|
|
|
382
433
|
const msg = {
|
|
383
434
|
type: "bridge_status",
|
|
384
435
|
connected: true,
|
|
436
|
+
bridgeVersion: getPackageVersion(),
|
|
385
437
|
chromeProfiles: getChromeProfilesList(),
|
|
386
438
|
timestamp: Date.now()
|
|
387
439
|
};
|
|
@@ -460,6 +512,28 @@ function startBridge(options) {
|
|
|
460
512
|
} else if (type === "bridge_status" || type === "bridge_closing") {
|
|
461
513
|
process.stderr.write(`${LOG_PREFIX2} Ignoring ${type} from MCP Server ${connId}
|
|
462
514
|
`);
|
|
515
|
+
} else if (type === "bridge_shutdown_request") {
|
|
516
|
+
process.stderr.write(`${LOG_PREFIX2} Shutdown requested by MCP Server ${connId}
|
|
517
|
+
`);
|
|
518
|
+
const DRAIN_TIMEOUT = 5e3;
|
|
519
|
+
const drainAndExit = () => {
|
|
520
|
+
if (requestOrigin.size === 0) {
|
|
521
|
+
gracefulExit("Bridge shutdown requested for version update");
|
|
522
|
+
return;
|
|
523
|
+
}
|
|
524
|
+
process.stderr.write(
|
|
525
|
+
`${LOG_PREFIX2} Waiting for ${requestOrigin.size} pending request(s) to drain...
|
|
526
|
+
`
|
|
527
|
+
);
|
|
528
|
+
const start = Date.now();
|
|
529
|
+
const check = setInterval(() => {
|
|
530
|
+
if (requestOrigin.size === 0 || Date.now() - start > DRAIN_TIMEOUT) {
|
|
531
|
+
clearInterval(check);
|
|
532
|
+
gracefulExit("Bridge shutdown requested for version update");
|
|
533
|
+
}
|
|
534
|
+
}, 200);
|
|
535
|
+
};
|
|
536
|
+
drainAndExit();
|
|
463
537
|
} else {
|
|
464
538
|
sendToChrome(agentId ? getChromeForAgent(agentId) : primaryChromeId, message);
|
|
465
539
|
}
|
|
@@ -567,13 +641,11 @@ function startBridge(options) {
|
|
|
567
641
|
if (chromeConnections.size === 0 && mcpConnections.size === 0) {
|
|
568
642
|
gracefulExit("No connections remaining");
|
|
569
643
|
}
|
|
570
|
-
if (chromeConnections.size === 0 && !orphanTimer) {
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
}
|
|
576
|
-
}, ORPHAN_TIMEOUT);
|
|
644
|
+
if (chromeConnections.size === 0 && mcpConnections.size > 0 && !orphanTimer) {
|
|
645
|
+
process.stderr.write(
|
|
646
|
+
`${LOG_PREFIX2} No Chrome connections, but ${mcpConnections.size} MCP Server(s) connected \u2014 waiting for Chrome relay
|
|
647
|
+
`
|
|
648
|
+
);
|
|
577
649
|
}
|
|
578
650
|
}
|
|
579
651
|
function setupRelayConnection(socket) {
|
|
@@ -686,6 +758,7 @@ function startBridge(options) {
|
|
|
686
758
|
sendToMcp(connId, {
|
|
687
759
|
type: "bridge_status",
|
|
688
760
|
connected: true,
|
|
761
|
+
bridgeVersion: getPackageVersion(),
|
|
689
762
|
chromeProfiles: getChromeProfilesList(),
|
|
690
763
|
timestamp: Date.now()
|
|
691
764
|
});
|
|
@@ -772,7 +845,7 @@ function startBridge(options) {
|
|
|
772
845
|
|
|
773
846
|
// src/server.ts
|
|
774
847
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
775
|
-
import { existsSync, mkdirSync, readFileSync, statSync, unlinkSync, writeFileSync } from "fs";
|
|
848
|
+
import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync, statSync, unlinkSync as unlinkSync2, writeFileSync } from "fs";
|
|
776
849
|
import http from "http";
|
|
777
850
|
import { createConnection as createConnection2 } from "net";
|
|
778
851
|
import { dirname } from "path";
|
|
@@ -894,7 +967,11 @@ var lastHeartbeat = null;
|
|
|
894
967
|
var chromeProfiles = [];
|
|
895
968
|
function setExtensionConnected(connected) {
|
|
896
969
|
extensionConnected = connected;
|
|
897
|
-
if (connected)
|
|
970
|
+
if (connected) {
|
|
971
|
+
lastHeartbeat = Date.now();
|
|
972
|
+
} else {
|
|
973
|
+
chromeProfiles = [];
|
|
974
|
+
}
|
|
898
975
|
}
|
|
899
976
|
function recordHeartbeat() {
|
|
900
977
|
lastHeartbeat = Date.now();
|
|
@@ -3286,7 +3363,7 @@ var scrollTool = {
|
|
|
3286
3363
|
tabId: z.coerce.number().describe("Tab ID"),
|
|
3287
3364
|
coordinate: z.tuple([z.coerce.number(), z.coerce.number()]).optional().describe("Scroll position [x, y] (required for directional scroll)"),
|
|
3288
3365
|
direction: z.enum(["up", "down", "left", "right"]).optional().describe("Scroll direction (required for directional scroll)"),
|
|
3289
|
-
amount: z.coerce.number().min(1).max(10).optional().describe("Scroll amount (default: 3)"),
|
|
3366
|
+
amount: z.coerce.number().min(1).max(10).optional().describe("Scroll amount in viewport fractions: 3 = one full viewport (default: 3)"),
|
|
3290
3367
|
ref: z.string().optional().describe("Element reference ID to scroll into view")
|
|
3291
3368
|
})
|
|
3292
3369
|
};
|
|
@@ -4844,6 +4921,7 @@ function computeToolTimeout(tool, input) {
|
|
|
4844
4921
|
// src/server.ts
|
|
4845
4922
|
var pendingRequests = /* @__PURE__ */ new Map();
|
|
4846
4923
|
var extensionSocket = null;
|
|
4924
|
+
var bridgeUpdateInfo = null;
|
|
4847
4925
|
var configuredChromeProfile;
|
|
4848
4926
|
function coerceValue(v) {
|
|
4849
4927
|
if (typeof v !== "string") return v;
|
|
@@ -4865,7 +4943,7 @@ function coerceShape(shape) {
|
|
|
4865
4943
|
return result;
|
|
4866
4944
|
}
|
|
4867
4945
|
function handleFileExport(filePath, result) {
|
|
4868
|
-
|
|
4946
|
+
mkdirSync2(dirname(filePath), { recursive: true });
|
|
4869
4947
|
let content;
|
|
4870
4948
|
let metadata;
|
|
4871
4949
|
if (typeof result.data === "string") {
|
|
@@ -4929,6 +5007,14 @@ function createConfiguredMcpServer() {
|
|
|
4929
5007
|
} catch {
|
|
4930
5008
|
}
|
|
4931
5009
|
}
|
|
5010
|
+
if (bridgeUpdateInfo) {
|
|
5011
|
+
const info = bridgeUpdateInfo;
|
|
5012
|
+
bridgeUpdateInfo = null;
|
|
5013
|
+
result.content.unshift({
|
|
5014
|
+
type: "text",
|
|
5015
|
+
text: `[INFO] Bridge was restarted for version update (${info.from} \u2192 ${info.to}). Connection re-established.`
|
|
5016
|
+
});
|
|
5017
|
+
}
|
|
4932
5018
|
return result;
|
|
4933
5019
|
});
|
|
4934
5020
|
}
|
|
@@ -5219,7 +5305,7 @@ async function handleStreamableHttpRequest(req, res, sessions2) {
|
|
|
5219
5305
|
}
|
|
5220
5306
|
var MAX_BODY_SIZE = 4 * 1024 * 1024;
|
|
5221
5307
|
function parseJsonBody(req) {
|
|
5222
|
-
return new Promise((
|
|
5308
|
+
return new Promise((resolve3, reject) => {
|
|
5223
5309
|
const chunks = [];
|
|
5224
5310
|
let size = 0;
|
|
5225
5311
|
let destroyed = false;
|
|
@@ -5237,7 +5323,7 @@ function parseJsonBody(req) {
|
|
|
5237
5323
|
req.on("end", () => {
|
|
5238
5324
|
if (destroyed) return;
|
|
5239
5325
|
try {
|
|
5240
|
-
|
|
5326
|
+
resolve3(JSON.parse(Buffer.concat(chunks).toString("utf-8")));
|
|
5241
5327
|
} catch (error) {
|
|
5242
5328
|
reject(new Error(`Invalid JSON: ${error.message}`));
|
|
5243
5329
|
}
|
|
@@ -5445,6 +5531,21 @@ function handleExtensionMessage(message) {
|
|
|
5445
5531
|
}
|
|
5446
5532
|
}
|
|
5447
5533
|
}
|
|
5534
|
+
const bridgeVersion = typeof msg.bridgeVersion === "string" ? msg.bridgeVersion : null;
|
|
5535
|
+
if (bridgeVersion && shouldUpdateBridge(bridgeVersion)) {
|
|
5536
|
+
const serverVersion = getPackageVersion();
|
|
5537
|
+
process.stderr.write(
|
|
5538
|
+
`[viyv-browser:mcp] Bridge version mismatch (bridge=${bridgeVersion}, server=${serverVersion}), requesting restart
|
|
5539
|
+
`
|
|
5540
|
+
);
|
|
5541
|
+
bridgeUpdateInfo = { from: bridgeVersion, to: serverVersion };
|
|
5542
|
+
if (extensionSocket && !extensionSocket.destroyed) {
|
|
5543
|
+
extensionSocket.write(
|
|
5544
|
+
`${JSON.stringify({ type: "bridge_shutdown_request", timestamp: Date.now() })}
|
|
5545
|
+
`
|
|
5546
|
+
);
|
|
5547
|
+
}
|
|
5548
|
+
}
|
|
5448
5549
|
} else if (type === "browser_event") {
|
|
5449
5550
|
process.stderr.write(`[viyv-browser:mcp] Browser event: ${String(msg.eventType)}
|
|
5450
5551
|
`);
|
|
@@ -5582,7 +5683,7 @@ async function callExtensionTool(tool, input) {
|
|
|
5582
5683
|
if (paths) {
|
|
5583
5684
|
for (const p of paths) {
|
|
5584
5685
|
try {
|
|
5585
|
-
if (!
|
|
5686
|
+
if (!existsSync2(p) || !statSync(p).isFile()) {
|
|
5586
5687
|
return {
|
|
5587
5688
|
content: [
|
|
5588
5689
|
{
|
|
@@ -5614,7 +5715,7 @@ async function callExtensionTool(tool, input) {
|
|
|
5614
5715
|
let csvData;
|
|
5615
5716
|
if (typeof input.file_path === "string") {
|
|
5616
5717
|
const fp = input.file_path;
|
|
5617
|
-
if (!
|
|
5718
|
+
if (!existsSync2(fp) || !statSync(fp).isFile()) {
|
|
5618
5719
|
return {
|
|
5619
5720
|
content: [
|
|
5620
5721
|
{
|
|
@@ -5672,13 +5773,13 @@ async function callExtensionTool(tool, input) {
|
|
|
5672
5773
|
touchSession(agentId);
|
|
5673
5774
|
const sock = extensionSocket;
|
|
5674
5775
|
const toolTimeout = computeToolTimeout(tool, input);
|
|
5675
|
-
return new Promise((
|
|
5776
|
+
return new Promise((resolve3) => {
|
|
5676
5777
|
const onError = () => {
|
|
5677
5778
|
const pending = pendingRequests.get(requestId);
|
|
5678
5779
|
if (pending) {
|
|
5679
5780
|
clearTimeout(pending.timer);
|
|
5680
5781
|
pendingRequests.delete(requestId);
|
|
5681
|
-
|
|
5782
|
+
resolve3({
|
|
5682
5783
|
content: [
|
|
5683
5784
|
{
|
|
5684
5785
|
type: "text",
|
|
@@ -5699,7 +5800,7 @@ async function callExtensionTool(tool, input) {
|
|
|
5699
5800
|
const timer = setTimeout(() => {
|
|
5700
5801
|
pendingRequests.delete(requestId);
|
|
5701
5802
|
removeErrorListener();
|
|
5702
|
-
|
|
5803
|
+
resolve3({
|
|
5703
5804
|
content: [
|
|
5704
5805
|
{
|
|
5705
5806
|
type: "text",
|
|
@@ -5724,12 +5825,12 @@ async function callExtensionTool(tool, input) {
|
|
|
5724
5825
|
if (FILE_EXPORT_TOOLS.has(tool) && typeof filePath === "string" && ("data" in result || "pages" in result)) {
|
|
5725
5826
|
try {
|
|
5726
5827
|
const metadata = handleFileExport(filePath, result);
|
|
5727
|
-
|
|
5828
|
+
resolve3({
|
|
5728
5829
|
content: [{ type: "text", text: JSON.stringify(metadata) }]
|
|
5729
5830
|
});
|
|
5730
5831
|
} catch (e) {
|
|
5731
5832
|
const msg = e instanceof Error ? e.message : String(e);
|
|
5732
|
-
|
|
5833
|
+
resolve3({
|
|
5733
5834
|
content: [
|
|
5734
5835
|
{
|
|
5735
5836
|
type: "text",
|
|
@@ -5748,9 +5849,9 @@ async function callExtensionTool(tool, input) {
|
|
|
5748
5849
|
if (RESULT_EXPORT_TOOLS.has(tool) && typeof filePath === "string") {
|
|
5749
5850
|
try {
|
|
5750
5851
|
const content = JSON.stringify(result, null, 2);
|
|
5751
|
-
|
|
5852
|
+
mkdirSync2(dirname(filePath), { recursive: true });
|
|
5752
5853
|
writeFileSync(filePath, content, "utf-8");
|
|
5753
|
-
|
|
5854
|
+
resolve3({
|
|
5754
5855
|
content: [
|
|
5755
5856
|
{
|
|
5756
5857
|
type: "text",
|
|
@@ -5763,7 +5864,7 @@ async function callExtensionTool(tool, input) {
|
|
|
5763
5864
|
});
|
|
5764
5865
|
} catch (e) {
|
|
5765
5866
|
const msg = e instanceof Error ? e.message : String(e);
|
|
5766
|
-
|
|
5867
|
+
resolve3({
|
|
5767
5868
|
content: [
|
|
5768
5869
|
{
|
|
5769
5870
|
type: "text",
|
|
@@ -5790,21 +5891,21 @@ async function callExtensionTool(tool, input) {
|
|
|
5790
5891
|
}
|
|
5791
5892
|
if (tempImportFile) {
|
|
5792
5893
|
try {
|
|
5793
|
-
|
|
5894
|
+
unlinkSync2(tempImportFile);
|
|
5794
5895
|
} catch {
|
|
5795
5896
|
}
|
|
5796
5897
|
}
|
|
5797
|
-
|
|
5898
|
+
resolve3({ content: buildResponseContent(tool, finalResult) });
|
|
5798
5899
|
},
|
|
5799
5900
|
reject: (error) => {
|
|
5800
5901
|
removeErrorListener();
|
|
5801
5902
|
if (tempImportFile) {
|
|
5802
5903
|
try {
|
|
5803
|
-
|
|
5904
|
+
unlinkSync2(tempImportFile);
|
|
5804
5905
|
} catch {
|
|
5805
5906
|
}
|
|
5806
5907
|
}
|
|
5807
|
-
|
|
5908
|
+
resolve3({
|
|
5808
5909
|
content: [
|
|
5809
5910
|
{
|
|
5810
5911
|
type: "text",
|
|
@@ -5856,12 +5957,12 @@ async function handleSwitchBrowser() {
|
|
|
5856
5957
|
setExtensionConnected(false);
|
|
5857
5958
|
}
|
|
5858
5959
|
process.stderr.write("[viyv-browser:mcp] switch_browser: waiting for bridge reconnection...\n");
|
|
5859
|
-
return new Promise((
|
|
5960
|
+
return new Promise((resolve3) => {
|
|
5860
5961
|
const checkInterval = setInterval(() => {
|
|
5861
5962
|
if (extensionSocket && !extensionSocket.destroyed && isExtensionConnected()) {
|
|
5862
5963
|
clearInterval(checkInterval);
|
|
5863
5964
|
clearTimeout(timer);
|
|
5864
|
-
|
|
5965
|
+
resolve3({
|
|
5865
5966
|
content: [
|
|
5866
5967
|
{
|
|
5867
5968
|
type: "text",
|
|
@@ -5876,7 +5977,7 @@ async function handleSwitchBrowser() {
|
|
|
5876
5977
|
}, 500);
|
|
5877
5978
|
const timer = setTimeout(() => {
|
|
5878
5979
|
clearInterval(checkInterval);
|
|
5879
|
-
|
|
5980
|
+
resolve3({
|
|
5880
5981
|
content: [
|
|
5881
5982
|
{
|
|
5882
5983
|
type: "text",
|
|
@@ -5895,27 +5996,24 @@ async function handleSwitchBrowser() {
|
|
|
5895
5996
|
|
|
5896
5997
|
// src/setup.ts
|
|
5897
5998
|
import { execSync } from "child_process";
|
|
5898
|
-
import { chmodSync, existsSync as
|
|
5899
|
-
import { homedir, platform } from "os";
|
|
5900
|
-
import { dirname as dirname2, resolve } from "path";
|
|
5999
|
+
import { chmodSync as chmodSync2, existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
6000
|
+
import { homedir as homedir2, platform } from "os";
|
|
6001
|
+
import { dirname as dirname2, resolve as resolve2 } from "path";
|
|
5901
6002
|
function runSetup(options = {}) {
|
|
5902
6003
|
const os = platform();
|
|
5903
|
-
const binaryPath = getBinaryPath();
|
|
5904
6004
|
console.log("Viyv Browser MCP - Native Messaging Host Setup");
|
|
5905
6005
|
console.log("================================================");
|
|
5906
6006
|
console.log(`Platform: ${os}`);
|
|
5907
|
-
console.log(`Binary: ${binaryPath}`);
|
|
5908
|
-
if (!existsSync2(binaryPath)) {
|
|
5909
|
-
console.error(`WARNING: Binary not found at ${binaryPath}`);
|
|
5910
|
-
console.error("The Native Messaging Host may not work until the binary is available.");
|
|
5911
|
-
}
|
|
5912
6007
|
const allowedOrigins = options.extensionId ? [`chrome-extension://${options.extensionId}/`] : ["chrome-extension://*/"];
|
|
5913
6008
|
if (!options.extensionId) {
|
|
5914
6009
|
process.stderr.write(
|
|
5915
6010
|
"WARNING: Using wildcard allowed_origins (chrome-extension://*/). This allows any Chrome extension to connect. For production, specify --extension-id to restrict access.\n"
|
|
5916
6011
|
);
|
|
5917
6012
|
}
|
|
5918
|
-
|
|
6013
|
+
syncNativeHostBinary();
|
|
6014
|
+
const nativeHostPath = getNativeHostBinaryPath();
|
|
6015
|
+
console.log(`Native host binary: ${nativeHostPath}`);
|
|
6016
|
+
const wrapperPath = createNativeHostWrapper(os, nativeHostPath);
|
|
5919
6017
|
const manifest = {
|
|
5920
6018
|
name: NATIVE_HOST_NAME,
|
|
5921
6019
|
description: "Viyv Browser MCP Native Messaging Host",
|
|
@@ -5927,9 +6025,9 @@ function runSetup(options = {}) {
|
|
|
5927
6025
|
const manifestDir = dirname2(manifestPath);
|
|
5928
6026
|
console.log(`Wrapper: ${wrapperPath}`);
|
|
5929
6027
|
console.log(`Manifest path: ${manifestPath}`);
|
|
5930
|
-
|
|
6028
|
+
mkdirSync3(manifestDir, { recursive: true });
|
|
5931
6029
|
writeFileSync2(manifestPath, JSON.stringify(manifest, null, 2));
|
|
5932
|
-
|
|
6030
|
+
chmodSync2(manifestPath, 420);
|
|
5933
6031
|
console.log("\nNative Messaging Host registered successfully!");
|
|
5934
6032
|
console.log("\nNext steps:");
|
|
5935
6033
|
console.log("1. Start the MCP Server: node <path>/dist/index.js");
|
|
@@ -5939,32 +6037,22 @@ function runSetup(options = {}) {
|
|
|
5939
6037
|
setupClaudeDesktopConfig();
|
|
5940
6038
|
}
|
|
5941
6039
|
}
|
|
5942
|
-
function getBinaryPath() {
|
|
5943
|
-
const whichCmd = process.platform === "win32" ? "where" : "which";
|
|
5944
|
-
try {
|
|
5945
|
-
const found = execSync(`${whichCmd} viyv-browser-mcp`, { encoding: "utf-8" }).trim();
|
|
5946
|
-
if (found) return found;
|
|
5947
|
-
} catch {
|
|
5948
|
-
}
|
|
5949
|
-
const currentScript = process.argv[1];
|
|
5950
|
-
return resolve(currentScript);
|
|
5951
|
-
}
|
|
5952
6040
|
function createNativeHostWrapper(os, binaryPath) {
|
|
5953
6041
|
const manifestDir = dirname2(getManifestPath(os));
|
|
5954
|
-
|
|
6042
|
+
mkdirSync3(manifestDir, { recursive: true });
|
|
5955
6043
|
const nodePath = getNodePath();
|
|
5956
6044
|
if (os === "win32") {
|
|
5957
|
-
const wrapperPath2 =
|
|
6045
|
+
const wrapperPath2 = resolve2(manifestDir, `${NATIVE_HOST_NAME}.bat`);
|
|
5958
6046
|
writeFileSync2(wrapperPath2, `@echo off\r
|
|
5959
6047
|
"${nodePath}" "${binaryPath}" --native-host\r
|
|
5960
6048
|
`);
|
|
5961
6049
|
return wrapperPath2;
|
|
5962
6050
|
}
|
|
5963
|
-
const wrapperPath =
|
|
6051
|
+
const wrapperPath = resolve2(manifestDir, `${NATIVE_HOST_NAME}.sh`);
|
|
5964
6052
|
writeFileSync2(wrapperPath, `#!/bin/bash
|
|
5965
6053
|
exec "${nodePath}" "${binaryPath}" --native-host
|
|
5966
6054
|
`);
|
|
5967
|
-
|
|
6055
|
+
chmodSync2(wrapperPath, 493);
|
|
5968
6056
|
return wrapperPath;
|
|
5969
6057
|
}
|
|
5970
6058
|
function getNodePath() {
|
|
@@ -5975,18 +6063,18 @@ function getNodePath() {
|
|
|
5975
6063
|
}
|
|
5976
6064
|
}
|
|
5977
6065
|
function getManifestPath(os) {
|
|
5978
|
-
const home =
|
|
6066
|
+
const home = homedir2();
|
|
5979
6067
|
switch (os) {
|
|
5980
6068
|
case "darwin":
|
|
5981
|
-
return
|
|
6069
|
+
return resolve2(
|
|
5982
6070
|
home,
|
|
5983
6071
|
"Library/Application Support/Google/Chrome/NativeMessagingHosts",
|
|
5984
6072
|
`${NATIVE_HOST_NAME}.json`
|
|
5985
6073
|
);
|
|
5986
6074
|
case "linux":
|
|
5987
|
-
return
|
|
6075
|
+
return resolve2(home, ".config/google-chrome/NativeMessagingHosts", `${NATIVE_HOST_NAME}.json`);
|
|
5988
6076
|
case "win32":
|
|
5989
|
-
return
|
|
6077
|
+
return resolve2(
|
|
5990
6078
|
home,
|
|
5991
6079
|
"AppData/Local/Google/Chrome/User Data/NativeMessagingHosts",
|
|
5992
6080
|
`${NATIVE_HOST_NAME}.json`
|
|
@@ -6006,7 +6094,7 @@ function setupClaudeDesktopConfig() {
|
|
|
6006
6094
|
const configPath = getClaudeDesktopConfigPath();
|
|
6007
6095
|
console.log(`Config path: ${configPath}`);
|
|
6008
6096
|
let config = {};
|
|
6009
|
-
if (
|
|
6097
|
+
if (existsSync3(configPath)) {
|
|
6010
6098
|
try {
|
|
6011
6099
|
config = JSON.parse(readFileSync2(configPath, "utf-8"));
|
|
6012
6100
|
} catch {
|
|
@@ -6028,7 +6116,7 @@ function setupClaudeDesktopConfig() {
|
|
|
6028
6116
|
env: { PATH: envPath }
|
|
6029
6117
|
};
|
|
6030
6118
|
const configDir = dirname2(configPath);
|
|
6031
|
-
|
|
6119
|
+
mkdirSync3(configDir, { recursive: true });
|
|
6032
6120
|
writeFileSync2(configPath, JSON.stringify(config, null, 2));
|
|
6033
6121
|
console.log(`npx path: ${npxPath}`);
|
|
6034
6122
|
console.log("\nClaude Desktop config updated successfully!");
|
|
@@ -6043,16 +6131,16 @@ function getNpxPath() {
|
|
|
6043
6131
|
}
|
|
6044
6132
|
}
|
|
6045
6133
|
function getClaudeDesktopConfigPath() {
|
|
6046
|
-
const home =
|
|
6134
|
+
const home = homedir2();
|
|
6047
6135
|
switch (process.platform) {
|
|
6048
6136
|
case "darwin":
|
|
6049
|
-
return
|
|
6137
|
+
return resolve2(home, "Library/Application Support/Claude/claude_desktop_config.json");
|
|
6050
6138
|
case "linux":
|
|
6051
|
-
return
|
|
6139
|
+
return resolve2(home, ".config/Claude/claude_desktop_config.json");
|
|
6052
6140
|
case "win32":
|
|
6053
|
-
return
|
|
6141
|
+
return resolve2(home, "AppData/Roaming/Claude/claude_desktop_config.json");
|
|
6054
6142
|
default:
|
|
6055
|
-
return
|
|
6143
|
+
return resolve2(home, ".config/Claude/claude_desktop_config.json");
|
|
6056
6144
|
}
|
|
6057
6145
|
}
|
|
6058
6146
|
|
|
@@ -6087,6 +6175,16 @@ if (args.includes("setup")) {
|
|
|
6087
6175
|
const port = portIdx >= 0 ? Number(args[portIdx + 1]) : void 0;
|
|
6088
6176
|
const chromeProfileIdx = args.indexOf("--chrome-profile");
|
|
6089
6177
|
const chromeProfile = chromeProfileIdx >= 0 ? args[chromeProfileIdx + 1] : process.env.VIYV_CHROME_PROFILE;
|
|
6178
|
+
if (isNativeHostDeployed()) {
|
|
6179
|
+
try {
|
|
6180
|
+
syncNativeHostBinary();
|
|
6181
|
+
} catch (err) {
|
|
6182
|
+
process.stderr.write(
|
|
6183
|
+
`[viyv-browser:mcp] WARNING: Failed to update native host binary: ${err.message}
|
|
6184
|
+
`
|
|
6185
|
+
);
|
|
6186
|
+
}
|
|
6187
|
+
}
|
|
6090
6188
|
startMcpServer(agentName, { transport: transportMode, port, chromeProfile });
|
|
6091
6189
|
}
|
|
6092
6190
|
//# sourceMappingURL=index.js.map
|