@beeos-ai/device-mcp-server 0.2.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.
Files changed (62) hide show
  1. package/LICENSE +201 -0
  2. package/dist/backends/android-adb-runner.d.ts +32 -0
  3. package/dist/backends/android-adb-runner.js +15 -0
  4. package/dist/backends/android-adb-runner.js.map +1 -0
  5. package/dist/backends/android-adb.d.ts +153 -0
  6. package/dist/backends/android-adb.js +723 -0
  7. package/dist/backends/android-adb.js.map +1 -0
  8. package/dist/backends/base.d.ts +150 -0
  9. package/dist/backends/base.js +116 -0
  10. package/dist/backends/base.js.map +1 -0
  11. package/dist/backends/desktop.d.ts +62 -0
  12. package/dist/backends/desktop.js +176 -0
  13. package/dist/backends/desktop.js.map +1 -0
  14. package/dist/backends/index.d.ts +63 -0
  15. package/dist/backends/index.js +105 -0
  16. package/dist/backends/index.js.map +1 -0
  17. package/dist/backends/linux.d.ts +69 -0
  18. package/dist/backends/linux.js +230 -0
  19. package/dist/backends/linux.js.map +1 -0
  20. package/dist/backends/mac.d.ts +154 -0
  21. package/dist/backends/mac.js +881 -0
  22. package/dist/backends/mac.js.map +1 -0
  23. package/dist/backends/stubs/ios.d.ts +17 -0
  24. package/dist/backends/stubs/ios.js +32 -0
  25. package/dist/backends/stubs/ios.js.map +1 -0
  26. package/dist/backends/stubs/macos.d.ts +13 -0
  27. package/dist/backends/stubs/macos.js +27 -0
  28. package/dist/backends/stubs/macos.js.map +1 -0
  29. package/dist/backends/stubs/windows.d.ts +69 -0
  30. package/dist/backends/stubs/windows.js +191 -0
  31. package/dist/backends/stubs/windows.js.map +1 -0
  32. package/dist/cli.d.ts +37 -0
  33. package/dist/cli.js +177 -0
  34. package/dist/cli.js.map +1 -0
  35. package/dist/index.d.ts +13 -0
  36. package/dist/index.js +14 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/server/action-mapping.d.ts +21 -0
  39. package/dist/server/action-mapping.js +153 -0
  40. package/dist/server/action-mapping.js.map +1 -0
  41. package/dist/server/app.d.ts +23 -0
  42. package/dist/server/app.js +157 -0
  43. package/dist/server/app.js.map +1 -0
  44. package/dist/server/tool-registry.d.ts +50 -0
  45. package/dist/server/tool-registry.js +504 -0
  46. package/dist/server/tool-registry.js.map +1 -0
  47. package/dist/util/adb-files.d.ts +92 -0
  48. package/dist/util/adb-files.js +221 -0
  49. package/dist/util/adb-files.js.map +1 -0
  50. package/dist/util/adb-shell.d.ts +80 -0
  51. package/dist/util/adb-shell.js +102 -0
  52. package/dist/util/adb-shell.js.map +1 -0
  53. package/dist/util/android-apps.d.ts +10 -0
  54. package/dist/util/android-apps.js +103 -0
  55. package/dist/util/android-apps.js.map +1 -0
  56. package/dist/util/image-dim.d.ts +27 -0
  57. package/dist/util/image-dim.js +37 -0
  58. package/dist/util/image-dim.js.map +1 -0
  59. package/dist/util/ui-xml.d.ts +20 -0
  60. package/dist/util/ui-xml.js +184 -0
  61. package/dist/util/ui-xml.js.map +1 -0
  62. package/package.json +56 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @beeos-ai/device-mcp-server — public surface.
3
+ *
4
+ * Most callers use the CLI (`device-mcp-server`) and reach the server over
5
+ * HTTP. The exports here are for embedders that want to host a server in
6
+ * the same Node process (e.g. integration tests, custom orchestration).
7
+ */
8
+ export { buildApp, type BuildAppOptions } from "./server/app.js";
9
+ export { TOOLS, getTool, listToolDescriptors, type ToolEntry, type ToolHandler, type ToolHandlerContext, } from "./server/tool-registry.js";
10
+ export { mapActionToTool, type ActionMappingResult, type ToolCall, type UnsupportedActionResult, } from "./server/action-mapping.js";
11
+ export { AndroidAdbBackend, DesktopBackend, WindowsBackend, MacOsBackend, IosBackend, createBackend, SUPPORTED_BACKENDS, type BackendName, type SandboxBackend, type BackendFamily, type AndroidAdbBackendOptions, type DesktopBackendOptions, type CreateBackendOptions, } from "./backends/index.js";
12
+ export { BaseSandboxBackend, type ScreenSize, type UiDumpOutput, type ExecuteCommandOutput, type ListDirectoryEntry, } from "./backends/base.js";
13
+ export declare const VERSION = "0.2.0";
package/dist/index.js ADDED
@@ -0,0 +1,14 @@
1
+ /**
2
+ * @beeos-ai/device-mcp-server — public surface.
3
+ *
4
+ * Most callers use the CLI (`device-mcp-server`) and reach the server over
5
+ * HTTP. The exports here are for embedders that want to host a server in
6
+ * the same Node process (e.g. integration tests, custom orchestration).
7
+ */
8
+ export { buildApp } from "./server/app.js";
9
+ export { TOOLS, getTool, listToolDescriptors, } from "./server/tool-registry.js";
10
+ export { mapActionToTool, } from "./server/action-mapping.js";
11
+ export { AndroidAdbBackend, DesktopBackend, WindowsBackend, MacOsBackend, IosBackend, createBackend, SUPPORTED_BACKENDS, } from "./backends/index.js";
12
+ export { BaseSandboxBackend, } from "./backends/base.js";
13
+ export const VERSION = "0.2.0";
14
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,QAAQ,EAAwB,MAAM,iBAAiB,CAAC;AACjE,OAAO,EACL,KAAK,EACL,OAAO,EACP,mBAAmB,GAIpB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,eAAe,GAIhB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,cAAc,EACd,YAAY,EACZ,UAAU,EACV,aAAa,EACb,kBAAkB,GAOnB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,kBAAkB,GAKnB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * action-mapping — translate a unified `Action` (`type+target+payload`) into
3
+ * the matching MCP tool name + arguments.
4
+ *
5
+ * Used by `POST /act` so callers can hand the server a high-level Action and
6
+ * skip wiring up a tool name themselves. Mirrors the Python reference's
7
+ * `_action_to_call` table.
8
+ */
9
+ import { type Action, type ActionType } from "@beeos-ai/device-common";
10
+ export interface ToolCall {
11
+ toolName: string;
12
+ args: Record<string, unknown>;
13
+ }
14
+ export interface UnsupportedActionResult {
15
+ /** Terminal verbs (`done`, `fail`, `wait`, `call_for_user`) — server replies
16
+ * with `{ ok: true, action }` and does NOT touch the backend. */
17
+ terminal: true;
18
+ type: ActionType;
19
+ }
20
+ export type ActionMappingResult = ToolCall | UnsupportedActionResult;
21
+ export declare function mapActionToTool(action: Action): ActionMappingResult;
@@ -0,0 +1,153 @@
1
+ /**
2
+ * action-mapping — translate a unified `Action` (`type+target+payload`) into
3
+ * the matching MCP tool name + arguments.
4
+ *
5
+ * Used by `POST /act` so callers can hand the server a high-level Action and
6
+ * skip wiring up a tool name themselves. Mirrors the Python reference's
7
+ * `_action_to_call` table.
8
+ */
9
+ import { TERMINAL_ACTIONS, } from "@beeos-ai/device-common";
10
+ export function mapActionToTool(action) {
11
+ if (TERMINAL_ACTIONS.has(action.type) || action.type === "wait") {
12
+ return { terminal: true, type: action.type };
13
+ }
14
+ const target = action.target;
15
+ const payload = action.payload ?? {};
16
+ switch (action.type) {
17
+ case "click":
18
+ case "tap":
19
+ case "double_click":
20
+ case "right_click":
21
+ case "long_press":
22
+ case "move": {
23
+ const xy = pointFromTarget(target);
24
+ return {
25
+ toolName: action.type === "move" ? "move" : action.type,
26
+ args: {
27
+ ...xy,
28
+ ...(action.type === "click" && payload.button ? { button: payload.button } : {}),
29
+ ...(action.type === "click" && payload.clicks ? { clicks: payload.clicks } : {}),
30
+ ...(action.type === "long_press" && payload.durationMs
31
+ ? { durationMs: payload.durationMs }
32
+ : {}),
33
+ },
34
+ };
35
+ }
36
+ case "drag":
37
+ case "swipe": {
38
+ const seg = segmentFromTarget(target);
39
+ return {
40
+ toolName: action.type,
41
+ args: {
42
+ ...seg,
43
+ ...(payload.durationMs ? { durationMs: payload.durationMs } : {}),
44
+ },
45
+ };
46
+ }
47
+ case "scroll": {
48
+ const xy = target ? pointFromTarget(target) : { x: 0, y: 0 };
49
+ return {
50
+ toolName: "scroll",
51
+ args: {
52
+ ...xy,
53
+ direction: payload.direction ?? "down",
54
+ ...(payload.amount ? { amount: payload.amount } : {}),
55
+ },
56
+ };
57
+ }
58
+ case "type":
59
+ return {
60
+ toolName: "type",
61
+ args: { text: payload.text ?? "" },
62
+ };
63
+ case "key":
64
+ return {
65
+ toolName: "key",
66
+ args: { key: payload.key ?? payload.keycode ?? "" },
67
+ };
68
+ case "hotkey":
69
+ return {
70
+ toolName: "hotkey",
71
+ args: { keys: payload.keys ?? [] },
72
+ };
73
+ case "back":
74
+ return { toolName: "back", args: {} };
75
+ case "home":
76
+ return { toolName: "home", args: {} };
77
+ case "navigate":
78
+ return {
79
+ toolName: "back",
80
+ args: {},
81
+ };
82
+ case "launch_app": {
83
+ const fromTarget = target && (target.kind === "text" || target.kind === "selector")
84
+ ? target.value
85
+ : undefined;
86
+ const pkg = fromTarget ??
87
+ payload.pkg ??
88
+ payload.appName ??
89
+ payload.packageOrName ??
90
+ payload.package ??
91
+ "";
92
+ return {
93
+ toolName: "launch_app",
94
+ args: {
95
+ pkg,
96
+ ...(payload.activity ? { activity: payload.activity } : {}),
97
+ },
98
+ };
99
+ }
100
+ case "screenshot":
101
+ return { toolName: "screenshot", args: {} };
102
+ case "ui_dump":
103
+ return {
104
+ toolName: "ui_dump",
105
+ args: {
106
+ ...(payload.query ? { query: payload.query } : {}),
107
+ ...(payload.format ? { format: payload.format } : {}),
108
+ },
109
+ };
110
+ case "execute_command":
111
+ case "run_code":
112
+ return {
113
+ toolName: "execute_command",
114
+ args: {
115
+ body: payload.body ?? payload.command ?? "",
116
+ ...(payload.timeoutS ? { timeoutS: payload.timeoutS } : {}),
117
+ ...(payload.cwd ? { cwd: payload.cwd } : {}),
118
+ },
119
+ };
120
+ case "file_read": {
121
+ const path = payload.path ??
122
+ (target && (target.kind === "text" || target.kind === "selector")
123
+ ? target.value
124
+ : "");
125
+ return { toolName: "file_read", args: { path } };
126
+ }
127
+ case "file_write": {
128
+ const path = payload.path ??
129
+ (target && (target.kind === "text" || target.kind === "selector")
130
+ ? target.value
131
+ : "");
132
+ return {
133
+ toolName: "file_write",
134
+ args: { path, contentB64: payload.contentB64 ?? "" },
135
+ };
136
+ }
137
+ default:
138
+ throw new Error(`unsupported action type: ${String(action.type)}`);
139
+ }
140
+ }
141
+ function pointFromTarget(target) {
142
+ if (target && target.kind === "point") {
143
+ return { x: target.x, y: target.y };
144
+ }
145
+ throw new TypeError("action.target must be {kind:'point', x, y} for this action type");
146
+ }
147
+ function segmentFromTarget(target) {
148
+ if (target && target.kind === "box") {
149
+ return { x1: target.x1, y1: target.y1, x2: target.x2, y2: target.y2 };
150
+ }
151
+ throw new TypeError("action.target must be {kind:'box', x1, y1, x2, y2} for this action type");
152
+ }
153
+ //# sourceMappingURL=action-mapping.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"action-mapping.js","sourceRoot":"","sources":["../../src/server/action-mapping.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Fastify factory — `buildApp({ backend })` returns a configured `FastifyInstance`
3
+ * with all routes wired up. Decoupled from `cli.ts` so unit tests can spin up
4
+ * an in-process server with a mock backend.
5
+ *
6
+ * Routes (mirrors the Python `mcp_tools/server.py` reference):
7
+ * GET /healthz — liveness + backend OS + tool list
8
+ * POST /mcp/tools/list — MCP tool discovery
9
+ * POST /mcp/tools/call — invoke a single MCP tool
10
+ * POST /act — translate `Action` → tool call
11
+ * GET /screen.png — fast-path screenshot (no JSON envelope)
12
+ * GET /events — SSE event stream (placeholder, no consumers yet)
13
+ */
14
+ import { type FastifyInstance } from "fastify";
15
+ import type { SandboxBackend } from "../backends/base.js";
16
+ export interface BuildAppOptions {
17
+ backend: SandboxBackend;
18
+ /** Override Fastify's logger. Pass `false` to silence in tests. */
19
+ logger?: boolean | object;
20
+ /** Per-request body size cap (bytes). Defaults to 16MB for file_write base64. */
21
+ bodyLimit?: number;
22
+ }
23
+ export declare function buildApp(opts: BuildAppOptions): Promise<FastifyInstance>;
@@ -0,0 +1,157 @@
1
+ /**
2
+ * Fastify factory — `buildApp({ backend })` returns a configured `FastifyInstance`
3
+ * with all routes wired up. Decoupled from `cli.ts` so unit tests can spin up
4
+ * an in-process server with a mock backend.
5
+ *
6
+ * Routes (mirrors the Python `mcp_tools/server.py` reference):
7
+ * GET /healthz — liveness + backend OS + tool list
8
+ * POST /mcp/tools/list — MCP tool discovery
9
+ * POST /mcp/tools/call — invoke a single MCP tool
10
+ * POST /act — translate `Action` → tool call
11
+ * GET /screen.png — fast-path screenshot (no JSON envelope)
12
+ * GET /events — SSE event stream (placeholder, no consumers yet)
13
+ */
14
+ import Fastify from "fastify";
15
+ import { AcpError, DeviceError, VlmError, } from "@beeos-ai/device-common";
16
+ import { mapActionToTool } from "./action-mapping.js";
17
+ import { getToolFor, listToolDescriptorsFor } from "./tool-registry.js";
18
+ export async function buildApp(opts) {
19
+ const app = Fastify({
20
+ logger: opts.logger ?? true,
21
+ bodyLimit: opts.bodyLimit ?? 16 * 1024 * 1024,
22
+ });
23
+ app.setErrorHandler((err, _req, reply) => {
24
+ if (err instanceof DeviceError) {
25
+ const status = err.subtype === "unsupported" ? 501 : err.subtype === "invalid_args" ? 400 : 500;
26
+ reply
27
+ .status(status)
28
+ .send({ error: err.message, subtype: err.subtype, retriable: err.retriable });
29
+ return;
30
+ }
31
+ if (err instanceof AcpError) {
32
+ reply.status(400).send({ error: err.message, code: err.code });
33
+ return;
34
+ }
35
+ if (err instanceof VlmError) {
36
+ reply.status(400).send({ error: err.message, retriable: err.retriable });
37
+ return;
38
+ }
39
+ reply.status(500).send({ error: err?.message ?? "internal error" });
40
+ });
41
+ /* ---------- /healthz ---------- */
42
+ app.get("/healthz", async () => {
43
+ return {
44
+ ok: true,
45
+ // Wire field name kept as `backend` even though the source is
46
+ // now `os` rather than `family`. Values are unchanged
47
+ // (`"android"` / `"desktop-macos"` / etc) — see the BackendOs
48
+ // taxonomy in @beeos-ai/device-common/backend.ts.
49
+ backend: opts.backend.os,
50
+ version: process.env.npm_package_version ?? "0.2.0",
51
+ // Tool-set-filtered list — agents that pick a tool out of this
52
+ // list are guaranteed it'll dispatch on the active backend.
53
+ tools: listToolDescriptorsFor(opts.backend).map((t) => t.name),
54
+ };
55
+ });
56
+ /* ---------- /mcp/tools/list ---------- */
57
+ const toolListHandler = async () => ({
58
+ tools: listToolDescriptorsFor(opts.backend),
59
+ });
60
+ app.get("/mcp/tools/list", toolListHandler);
61
+ app.post("/mcp/tools/list", toolListHandler);
62
+ /* ---------- /mcp/tools/call ---------- */
63
+ app.post("/mcp/tools/call", async (req, reply) => {
64
+ const { name, arguments: args = {} } = req.body ?? {};
65
+ if (!name || typeof name !== "string") {
66
+ reply.status(400).send({ error: "missing tool name" });
67
+ return;
68
+ }
69
+ const tool = getToolFor(name, opts.backend);
70
+ if (!tool) {
71
+ // Either the tool is unknown OR the backend lacks the required
72
+ // capability — collapse both to 404 so MCP clients reading
73
+ // `/mcp/tools/list` cannot bypass the filter via direct call.
74
+ reply.status(404).send({ error: `unknown tool '${name}'` });
75
+ return;
76
+ }
77
+ const startedAt = Date.now();
78
+ try {
79
+ const result = await tool.handler(args, { backend: opts.backend });
80
+ const response = {
81
+ ok: true,
82
+ tool: name,
83
+ durationMs: Date.now() - startedAt,
84
+ result,
85
+ };
86
+ reply.send(response);
87
+ }
88
+ catch (e) {
89
+ if (e instanceof DeviceError)
90
+ throw e;
91
+ if (e instanceof Error && e.name === "TypeError") {
92
+ reply.status(400).send({ error: e.message });
93
+ return;
94
+ }
95
+ throw e;
96
+ }
97
+ });
98
+ /* ---------- /act ---------- */
99
+ app.post("/act", async (req, reply) => {
100
+ const action = req.body?.action;
101
+ if (!action || typeof action.type !== "string") {
102
+ reply.status(400).send({ error: "missing or malformed action" });
103
+ return;
104
+ }
105
+ const startedAt = Date.now();
106
+ const mapped = mapActionToTool(action);
107
+ if ("terminal" in mapped) {
108
+ const response = {
109
+ ok: true,
110
+ action: mapped.type,
111
+ terminal: true,
112
+ durationMs: Date.now() - startedAt,
113
+ };
114
+ reply.send(response);
115
+ return;
116
+ }
117
+ const tool = getToolFor(mapped.toolName, opts.backend);
118
+ if (!tool) {
119
+ reply.status(404).send({ error: `tool '${mapped.toolName}' not registered` });
120
+ return;
121
+ }
122
+ const result = await tool.handler(mapped.args, { backend: opts.backend });
123
+ const response = {
124
+ ok: true,
125
+ action: action.type,
126
+ tool: mapped.toolName,
127
+ durationMs: Date.now() - startedAt,
128
+ result,
129
+ };
130
+ reply.send(response);
131
+ });
132
+ /* ---------- /screen.png ---------- */
133
+ app.get("/screen.png", async (_req, reply) => {
134
+ // 0.2.3: backend reports the encoded format directly so we never
135
+ // need to magic-byte-sniff the buffer here.
136
+ const shot = await opts.backend.screenshot();
137
+ reply
138
+ .header("content-type", shot.format === "png" ? "image/png" : "image/jpeg")
139
+ .send(shot.data);
140
+ });
141
+ /* ---------- /events (SSE placeholder) ---------- */
142
+ app.get("/events", async (_req, reply) => {
143
+ reply.raw.writeHead(200, {
144
+ "Content-Type": "text/event-stream",
145
+ "Cache-Control": "no-cache",
146
+ Connection: "keep-alive",
147
+ });
148
+ reply.raw.write(": connected\n\n");
149
+ const interval = setInterval(() => {
150
+ reply.raw.write(`: heartbeat ${Date.now()}\n\n`);
151
+ }, 15_000);
152
+ reply.raw.on("close", () => clearInterval(interval));
153
+ return reply;
154
+ });
155
+ return app;
156
+ }
157
+ //# sourceMappingURL=app.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app.js","sourceRoot":"","sources":["../../src/server/app.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * MCP tool registry — verbs exposed by the device sandbox.
3
+ *
4
+ * Each tool entry carries:
5
+ * - a name (the MCP tool identifier, e.g. `click`)
6
+ * - a JSON schema describing the expected `arguments` payload
7
+ * - a `handler` that maps `arguments` → `SandboxBackend` method call.
8
+ *
9
+ * Filtering is driven entirely by `backend.tools` (a flat
10
+ * `ReadonlySet<string>` declared on each backend). The registry is
11
+ * purely a name → schema/handler lookup table; it does not encode
12
+ * support gates of its own. `listToolDescriptorsFor(backend)` filters
13
+ * via `backend.tools.has(name)`; `getToolFor(name, backend)` mirrors
14
+ * the same gate so `/mcp/tools/call` returns 404 (instead of 200 +
15
+ * runtime `unsupported`) for any tool the active backend doesn't
16
+ * advertise.
17
+ *
18
+ * Inspired by the Python `mcp_tools/registry.py` reference; verbs are kept
19
+ * verbatim for cross-runtime compatibility.
20
+ */
21
+ import type { ToolDescriptor } from "@beeos-ai/device-common";
22
+ import type { SandboxBackend } from "../backends/base.js";
23
+ export interface ToolHandlerContext {
24
+ backend: SandboxBackend;
25
+ }
26
+ export type ToolHandler = (args: Record<string, unknown>, ctx: ToolHandlerContext) => Promise<unknown>;
27
+ export interface ToolEntry {
28
+ descriptor: ToolDescriptor;
29
+ handler: ToolHandler;
30
+ }
31
+ export declare const TOOLS: Record<string, ToolEntry>;
32
+ /**
33
+ * Return ALL registered tool descriptors regardless of backend support.
34
+ *
35
+ * Useful for documentation / tests that want to enumerate the catalog.
36
+ * Wire callers SHOULD use `listToolDescriptorsFor(backend)` so the list
37
+ * only contains tools the active backend can actually execute.
38
+ */
39
+ export declare function listToolDescriptors(): ToolDescriptor[];
40
+ /** Return tool descriptors filtered by the backend's advertised tool set. */
41
+ export declare function listToolDescriptorsFor(backend: SandboxBackend): ToolDescriptor[];
42
+ /** Look up a tool by name, ignoring backend tool-set gates. */
43
+ export declare function getTool(name: string): ToolEntry | undefined;
44
+ /**
45
+ * Look up a tool by name, **gated** on the backend's advertised tool
46
+ * set. Returns `undefined` for tools the active backend cannot
47
+ * satisfy — the `/mcp/tools/call` route uses this and returns 404,
48
+ * mirroring the filtering applied at `/mcp/tools/list`.
49
+ */
50
+ export declare function getToolFor(name: string, backend: SandboxBackend): ToolEntry | undefined;