@extentos/mcp-server 0.0.6 → 0.0.7
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 +8 -1
- package/dist/index.js.map +1 -1
- package/dist/localBridge.d.ts +4 -0
- package/dist/localBridge.d.ts.map +1 -0
- package/dist/localBridge.js +70 -0
- package/dist/localBridge.js.map +1 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -10,12 +10,18 @@ import { toolDefinitions } from "./tools/definitions.js";
|
|
|
10
10
|
import { handlers } from "./tools/registry.js";
|
|
11
11
|
import { mcpErrorResponse } from "./stub.js";
|
|
12
12
|
import { drainTelemetry, emitInstalledOnce, emitToolCalled, } from "./telemetry/index.js";
|
|
13
|
+
import { startLocalBridge, stopLocalBridge } from "./localBridge.js";
|
|
13
14
|
const SERVER_NAME = "@extentos/mcp-server";
|
|
14
|
-
const SERVER_VERSION = "0.0.
|
|
15
|
+
const SERVER_VERSION = "0.0.7";
|
|
15
16
|
async function main() {
|
|
16
17
|
const server = new Server({ name: SERVER_NAME, version: SERVER_VERSION }, { capabilities: { tools: {} } });
|
|
17
18
|
// First-run install event (no-op if already fired or consent declined).
|
|
18
19
|
emitInstalledOnce({ mcpVersion: SERVER_VERSION });
|
|
20
|
+
// Local /whoami listener — drives the zero-touch auto-bind path. The
|
|
21
|
+
// library on the dev's emulator/phone probes 127.0.0.1:31337 (via
|
|
22
|
+
// 10.0.2.2 from the emulator, or `adb reverse` from USB devices) to
|
|
23
|
+
// learn this MCP's installId. Failure is harmless: typed-code fallback.
|
|
24
|
+
startLocalBridge();
|
|
19
25
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
20
26
|
tools: toolDefinitions.map((def) => ({
|
|
21
27
|
name: def.name,
|
|
@@ -56,6 +62,7 @@ async function main() {
|
|
|
56
62
|
// as a belt-and-braces for direct-invocation scenarios.
|
|
57
63
|
const drain = () => {
|
|
58
64
|
void drainTelemetry();
|
|
65
|
+
stopLocalBridge();
|
|
59
66
|
};
|
|
60
67
|
transport.onclose = drain;
|
|
61
68
|
process.once("SIGINT", drain);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,2CAA2C;AAC3C,wEAAwE;AACxE,sEAAsE;AACtE,uDAAuD;AAEvD,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EACL,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,oCAAoC,CAAC;AAE5C,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,cAAc,GAEf,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"localBridge.d.ts","sourceRoot":"","sources":["../src/localBridge.ts"],"names":[],"mappings":"AA0BA,eAAO,MAAM,iBAAiB,QAAQ,CAAC;AAIvC,wBAAgB,gBAAgB,IAAI,IAAI,CAsCvC;AAED,wBAAgB,eAAe,IAAI,IAAI,CAItC"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// Local /whoami listener for the device-side library to discover its host
|
|
2
|
+
// MCP server's installId at runtime. Powers the zero-touch auto-bind path
|
|
3
|
+
// in PERSISTENT_DEV_SESSION.md.
|
|
4
|
+
//
|
|
5
|
+
// How it's reached:
|
|
6
|
+
// - Android emulator: http://10.0.2.2:31337/whoami → maps to host's
|
|
7
|
+
// 127.0.0.1 by emulator NAT. Each emulator only sees its own host, so
|
|
8
|
+
// two devs sharing a public IP do NOT cross — that was the whole point
|
|
9
|
+
// of using localhost IPC instead of IP correlation.
|
|
10
|
+
// - Physical Android phone (USB): `adb reverse tcp:31337 tcp:31337` makes
|
|
11
|
+
// `localhost:31337` on the device reach this listener. One-line setup.
|
|
12
|
+
// - Cellular phone / cloud-hosted agent: probe times out, library falls
|
|
13
|
+
// back to the typed-code path.
|
|
14
|
+
//
|
|
15
|
+
// Bound to 127.0.0.1 deliberately. Other apps on the same machine can read
|
|
16
|
+
// the installId, which is not a secret — it's the same value the MCP sends
|
|
17
|
+
// to api.extentos.com on every tool call. No auth needed at this layer.
|
|
18
|
+
//
|
|
19
|
+
// Lifetime: starts at MCP boot, stops on process exit. Best-effort — if the
|
|
20
|
+
// port is in use (rare; another MCP instance running), startup logs a
|
|
21
|
+
// warning and continues. Auto-bind silently degrades to typed-code; the
|
|
22
|
+
// agent still works.
|
|
23
|
+
import { createServer } from "node:http";
|
|
24
|
+
import { resolveInstallId } from "./telemetry/installRegistry.js";
|
|
25
|
+
export const LOCAL_BRIDGE_PORT = 31337;
|
|
26
|
+
let server = null;
|
|
27
|
+
export function startLocalBridge() {
|
|
28
|
+
if (server)
|
|
29
|
+
return;
|
|
30
|
+
const installId = resolveInstallId();
|
|
31
|
+
server = createServer((req, res) => {
|
|
32
|
+
if (req.method === "GET" && (req.url === "/whoami" || req.url?.startsWith("/whoami?"))) {
|
|
33
|
+
res.writeHead(200, {
|
|
34
|
+
"content-type": "application/json",
|
|
35
|
+
// Same-origin doesn't apply (this listener is reached over IP, not a
|
|
36
|
+
// browser fetch from another origin), but we set a permissive CORS
|
|
37
|
+
// header anyway in case a future browser-based dev tool wants to
|
|
38
|
+
// probe it from a localhost web app.
|
|
39
|
+
"access-control-allow-origin": "*",
|
|
40
|
+
});
|
|
41
|
+
res.end(JSON.stringify({
|
|
42
|
+
mcpInstallId: installId,
|
|
43
|
+
version: 1,
|
|
44
|
+
}));
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
res.writeHead(404, { "content-type": "application/json" });
|
|
48
|
+
res.end(JSON.stringify({ error: "not_found" }));
|
|
49
|
+
});
|
|
50
|
+
server.on("error", (err) => {
|
|
51
|
+
if (err.code === "EADDRINUSE") {
|
|
52
|
+
console.error(`[extentos-mcp] localBridge: port ${LOCAL_BRIDGE_PORT} in use — another MCP instance? auto-bind degraded to typed-code.`);
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
console.error(`[extentos-mcp] localBridge error:`, err);
|
|
56
|
+
}
|
|
57
|
+
server = null;
|
|
58
|
+
});
|
|
59
|
+
// Bind to 127.0.0.1 only. The Android emulator's 10.0.2.2 alias maps to
|
|
60
|
+
// host loopback (127.0.0.1) — confirmed by Android docs and verified in
|
|
61
|
+
// dev. A real phone connected via USB needs `adb reverse` regardless.
|
|
62
|
+
server.listen(LOCAL_BRIDGE_PORT, "127.0.0.1");
|
|
63
|
+
}
|
|
64
|
+
export function stopLocalBridge() {
|
|
65
|
+
if (!server)
|
|
66
|
+
return;
|
|
67
|
+
server.close();
|
|
68
|
+
server = null;
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=localBridge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"localBridge.js","sourceRoot":"","sources":["../src/localBridge.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,0EAA0E;AAC1E,gCAAgC;AAChC,EAAE;AACF,oBAAoB;AACpB,sEAAsE;AACtE,0EAA0E;AAC1E,2EAA2E;AAC3E,wDAAwD;AACxD,4EAA4E;AAC5E,2EAA2E;AAC3E,0EAA0E;AAC1E,mCAAmC;AACnC,EAAE;AACF,2EAA2E;AAC3E,2EAA2E;AAC3E,wEAAwE;AACxE,EAAE;AACF,4EAA4E;AAC5E,sEAAsE;AACtE,wEAAwE;AACxE,qBAAqB;AAErB,OAAO,EAAE,YAAY,EAAe,MAAM,WAAW,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAElE,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,CAAC;AAEvC,IAAI,MAAM,GAAkB,IAAI,CAAC;AAEjC,MAAM,UAAU,gBAAgB;IAC9B,IAAI,MAAM;QAAE,OAAO;IACnB,MAAM,SAAS,GAAG,gBAAgB,EAAE,CAAC;IACrC,MAAM,GAAG,YAAY,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QACjC,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,SAAS,IAAI,GAAG,CAAC,GAAG,EAAE,UAAU,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC;YACvF,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE;gBACjB,cAAc,EAAE,kBAAkB;gBAClC,qEAAqE;gBACrE,mEAAmE;gBACnE,iEAAiE;gBACjE,qCAAqC;gBACrC,6BAA6B,EAAE,GAAG;aACnC,CAAC,CAAC;YACH,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC;gBACrB,YAAY,EAAE,SAAS;gBACvB,OAAO,EAAE,CAAC;aACX,CAAC,CAAC,CAAC;YACJ,OAAO;QACT,CAAC;QACD,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;QAC3D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAA0B,EAAE,EAAE;QAChD,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;YAC9B,OAAO,CAAC,KAAK,CACX,oCAAoC,iBAAiB,mEAAmE,CACzH,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,GAAG,CAAC,CAAC;QAC1D,CAAC;QACD,MAAM,GAAG,IAAI,CAAC;IAChB,CAAC,CAAC,CAAC;IAEH,wEAAwE;IACxE,wEAAwE;IACxE,sEAAsE;IACtE,MAAM,CAAC,MAAM,CAAC,iBAAiB,EAAE,WAAW,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,IAAI,CAAC,MAAM;QAAE,OAAO;IACpB,MAAM,CAAC,KAAK,EAAE,CAAC;IACf,MAAM,GAAG,IAAI,CAAC;AAChB,CAAC"}
|