@adaptivemcp/mcp-binary 0.1.1
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 +143 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/rtk.d.ts +78 -0
- package/dist/rtk.d.ts.map +1 -0
- package/dist/rtk.js +107 -0
- package/dist/rtk.js.map +1 -0
- package/dist/server.d.ts +75 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +110 -0
- package/dist/server.js.map +1 -0
- package/package.json +32 -0
package/README.md
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# @adaptivemcp/mcp-binary
|
|
2
|
+
|
|
3
|
+
The **only sanctioned shell-out layer** in Adaptive MCP (see `docs/doubts.md` §12b / D10).
|
|
4
|
+
|
|
5
|
+
It wraps a CLI binary into an MCP stdio server, mapping the binary's CLI onto
|
|
6
|
+
MCP tools. Binaries like **rtk** (which has no native MCP server) become
|
|
7
|
+
chainable MCP servers this way, then attach to `@adaptivemcp/middleware` like
|
|
8
|
+
any other integration — instead of living at the host layer or shelling out
|
|
9
|
+
inside core.
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import { createRtkWrapper } from "@adaptivemcp/mcp-binary";
|
|
13
|
+
|
|
14
|
+
const rtk = createRtkWrapper(); // resolves the user's existing rtk install
|
|
15
|
+
if (rtk.available) {
|
|
16
|
+
await rtk.start(); // stdio MCP server exposing `rtk_exec`
|
|
17
|
+
}
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## What "MCP chaining" means here
|
|
21
|
+
|
|
22
|
+
Adaptive MCP does **not** chain binaries. It chains **MCP servers**.
|
|
23
|
+
|
|
24
|
+
- Each MCP server (yours, headroom's, rtk's wrapper) is a first-class node in a
|
|
25
|
+
`MiddlewareChain`.
|
|
26
|
+
- A middleware runs `beforeCall` / `afterCall` around a tool invocation. The
|
|
27
|
+
`afterCall` of one middleware sees the output produced by the previous one.
|
|
28
|
+
- The binary wrapper is just *one* node: it turns a CLI subprocess into an MCP
|
|
29
|
+
tool so it can participate in the chain. The chain itself is protocol-level,
|
|
30
|
+
not process-level.
|
|
31
|
+
|
|
32
|
+
So when you add rtk to the chain, you are not injecting rtk into every other
|
|
33
|
+
tool. You are adding a middleware that, for the tools you route through it, runs
|
|
34
|
+
a command via rtk and compresses the result. Other MCP tools are untouched
|
|
35
|
+
unless you explicitly route them through the rtk middleware.
|
|
36
|
+
|
|
37
|
+
## When / how rtk and headroom run
|
|
38
|
+
|
|
39
|
+
| | headroom | rtk (via this wrapper) |
|
|
40
|
+
| --- | --- | --- |
|
|
41
|
+
| Native MCP server? | Yes | No — wrapped here |
|
|
42
|
+
| Runs as | MCP server in the chain | CLI subprocess spawned by the wrapper |
|
|
43
|
+
| Trigger | `afterCall` compresses a tool's string output | `rtk_exec` tool runs a command through `rtk gain` |
|
|
44
|
+
| Effect on other tools | Only tools routed through the headroom middleware | Only tools routed through the rtk middleware |
|
|
45
|
+
| Telemetry | `headroom` view in `tools-metadata.yaml` | `rtk_exec` calls recorded like any MCP call |
|
|
46
|
+
|
|
47
|
+
**headroom** is a normal MCP server. Its `HeadroomMiddleware.afterCall` runs
|
|
48
|
+
after a tool returns and compresses the string output (D9: passthrough on
|
|
49
|
+
failure). It never spawns a process.
|
|
50
|
+
|
|
51
|
+
**rtk** has no MCP server, so `createRtkWrapper()` wraps the `rtk` CLI into one.
|
|
52
|
+
The wrapper exposes a single `rtk_exec` tool. When a tool in the chain calls
|
|
53
|
+
`rtk_exec`, the wrapper spawns `rtk gain <command>`, captures stdout, and
|
|
54
|
+
returns it. That is the *only* place in Adaptive MCP that spawns a process.
|
|
55
|
+
|
|
56
|
+
## Layering: this wrapper is NOT the rtk hook
|
|
57
|
+
|
|
58
|
+
rtk's own value comes from its **PreToolUse hook** (installed by `rtk init -g`),
|
|
59
|
+
which rewrites an agent's Bash calls (`git status` → `rtk git status`) *before*
|
|
60
|
+
they execute. That hook operates at the **agent's shell layer**.
|
|
61
|
+
|
|
62
|
+
This MCP wrapper is a **different layer**: it runs rtk as a normal CLI
|
|
63
|
+
subprocess *inside the Adaptive MCP middleware chain*, compressing the output of
|
|
64
|
+
a tool call that already returned.
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
Agent Bash layer: rtk hook rewrites `git status` → `rtk git status` (rtk's own feature)
|
|
68
|
+
│
|
|
69
|
+
▼
|
|
70
|
+
MCP tool-output layer: tool returns → rtk_exec middleware → `rtk gain` → compressed result
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
The two **compose** rather than conflict: the hook compresses what the agent
|
|
74
|
+
sends to the shell; this wrapper compresses what a tool's MCP result carries
|
|
75
|
+
back. Adaptive MCP does not install, enable, or disable the rtk hook — it only
|
|
76
|
+
reuses the rtk binary if it is already present.
|
|
77
|
+
|
|
78
|
+
## Graceful coexistence when rtk is already installed
|
|
79
|
+
|
|
80
|
+
If you already use rtk, Adaptive MCP is **not a nuisance** to your other MCPs:
|
|
81
|
+
|
|
82
|
+
1. **We reuse your install.** `resolveRtkCommand()` looks up your existing `rtk`
|
|
83
|
+
on `PATH` (or an explicit `command` path). We never download or install a
|
|
84
|
+
second copy, and we never touch your shell config or hook.
|
|
85
|
+
2. **We verify it's the right package.** A name collision exists: the Rust
|
|
86
|
+
*Type Kit* crate on crates.io is also called `rtk`. `resolveRtkCommand()`
|
|
87
|
+
probes `rtk --version` and only accepts a binary that prints `rtk <semver>`
|
|
88
|
+
(rtk-ai). If the `rtk` on `PATH` is the wrong package, the wrapper reports
|
|
89
|
+
`wrong-package` and degrades gracefully instead of silently misbehaving.
|
|
90
|
+
3. **We degrade, not crash.** If rtk is missing (or the wrong package), the
|
|
91
|
+
wrapper still constructs and registers its tools, but each `rtk_exec` call
|
|
92
|
+
returns a clear setup message (`isError: true`) instead of spawning a missing
|
|
93
|
+
binary. Check `server.available` to know the state up front.
|
|
94
|
+
4. **No double-compression surprise.** Because the hook and the wrapper are on
|
|
95
|
+
different layers, routing a tool through `rtk_exec` does not "double up" with
|
|
96
|
+
the hook — the hook affects what the agent runs in the shell; the wrapper
|
|
97
|
+
affects what a tool's MCP result carries back. They are independent knobs.
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
import { createRtkWrapper, resolveRtkCommand } from "@adaptivemcp/mcp-binary";
|
|
101
|
+
|
|
102
|
+
const resolution = resolveRtkCommand(); // { status: "found" | "missing" | "wrong-package" }
|
|
103
|
+
const rtk = createRtkWrapper(); // uses the resolved command automatically
|
|
104
|
+
|
|
105
|
+
if (!rtk.available) {
|
|
106
|
+
// resolution.detail explains why (missing, or wrong `rtk` package on PATH)
|
|
107
|
+
console.warn(resolution.detail);
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Telemetry integration
|
|
112
|
+
|
|
113
|
+
Every MCP call — including `rtk_exec` and headroom-compressed results — flows
|
|
114
|
+
through the same pipeline as any other tool:
|
|
115
|
+
|
|
116
|
+
```
|
|
117
|
+
tool call → TelemetryRecorder → MemoryStore (SQLite)
|
|
118
|
+
→ Evaluator (insights) → ExtensionController
|
|
119
|
+
→ tools-metadata.yaml (dev.adaptivemcp/tools-metadata)
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
`AdaptiveRuntime.observeCompleted(output)` accepts the (possibly compressed)
|
|
123
|
+
`output` and folds it into `ToolStats`. `MiddlewareChain.contributeView()`
|
|
124
|
+
surfaces per-middleware state under the `middleware:` map in
|
|
125
|
+
`tools-metadata.yaml` — e.g. `middleware: { headroom: { hash, savingsPercent } }`.
|
|
126
|
+
rtk's *own* opt-in telemetry (GDPR-gated, off by default) is separate and
|
|
127
|
+
untouched; Adaptive MCP only records the MCP-level calls it makes.
|
|
128
|
+
|
|
129
|
+
## API
|
|
130
|
+
|
|
131
|
+
- `createRtkWrapper(options?: RtkWrapperOptions): BinaryMcpServer` — wraps the
|
|
132
|
+
rtk CLI. `options.command` overrides discovery; `options.timeoutMs` bounds
|
|
133
|
+
each spawn; `options.version` sets the advertised server version.
|
|
134
|
+
- `resolveRtkCommand(command?: string): RtkResolution` — locates and verifies a
|
|
135
|
+
usable rtk-ai binary. Returns `{ status, command?, detail? }`.
|
|
136
|
+
- `BinaryMcpServer` — generic CLI→MCP wrapper. `available` getter, `name` /
|
|
137
|
+
`version` getters, `toolNames()`, `start()`, `close()`.
|
|
138
|
+
- `RTK_TOOLS` — the reference `BinaryToolSpec[]` (`rtk_exec` → `rtk gain`).
|
|
139
|
+
|
|
140
|
+
> **Secure by default.** Discovery is read-only: it probes `rtk --version` and
|
|
141
|
+
> never writes to the filesystem, mutates `PATH`, or installs software. If you
|
|
142
|
+
> need rtk, install it yourself from <https://rtk-ai.app> (Homebrew, the official
|
|
143
|
+
> checksum-hardened installer, or `cargo install`).
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @adaptivemcp/mcp-binary
|
|
3
|
+
*
|
|
4
|
+
* The **only** sanctioned shell-out layer in Adaptive MCP (doubts.md §12b / D10).
|
|
5
|
+
*
|
|
6
|
+
* It wraps a CLI binary into an MCP stdio server, mapping the binary's CLI onto
|
|
7
|
+
* MCP tools. Binaries like **rtk** (which has no native MCP server) become
|
|
8
|
+
* chainable MCP servers this way, then attach to `@adaptivemcp/middleware` like
|
|
9
|
+
* any other integration — instead of living at the host layer or shelling out
|
|
10
|
+
* inside core. `RtkWrapper` is the reference binary config.
|
|
11
|
+
*/
|
|
12
|
+
export { BinaryMcpServer } from "./server.js";
|
|
13
|
+
export type { BinaryMcpServerOptions, BinaryToolSpec } from "./server.js";
|
|
14
|
+
export { createRtkWrapper, RTK_TOOLS, resolveRtkCommand } from "./rtk.js";
|
|
15
|
+
export type { RtkWrapperOptions, RtkResolution } from "./rtk.js";
|
|
16
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,YAAY,EAAE,sBAAsB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC1E,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC1E,YAAY,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @adaptivemcp/mcp-binary
|
|
3
|
+
*
|
|
4
|
+
* The **only** sanctioned shell-out layer in Adaptive MCP (doubts.md §12b / D10).
|
|
5
|
+
*
|
|
6
|
+
* It wraps a CLI binary into an MCP stdio server, mapping the binary's CLI onto
|
|
7
|
+
* MCP tools. Binaries like **rtk** (which has no native MCP server) become
|
|
8
|
+
* chainable MCP servers this way, then attach to `@adaptivemcp/middleware` like
|
|
9
|
+
* any other integration — instead of living at the host layer or shelling out
|
|
10
|
+
* inside core. `RtkWrapper` is the reference binary config.
|
|
11
|
+
*/
|
|
12
|
+
export { BinaryMcpServer } from "./server.js";
|
|
13
|
+
export { createRtkWrapper, RTK_TOOLS, resolveRtkCommand } from "./rtk.js";
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC"}
|
package/dist/rtk.d.ts
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { BinaryMcpServer, type BinaryToolSpec } from "./server.js";
|
|
2
|
+
/**
|
|
3
|
+
* Reference binary config for **rtk** (rtk-ai.app).
|
|
4
|
+
*
|
|
5
|
+
* rtk has no native MCP server (doubts.md §12b, issue #1442 is "gauging
|
|
6
|
+
* interest" only), so it is wrapped here into an MCP server. The wrapper exposes
|
|
7
|
+
* a single `rtk_exec` tool that runs an arbitrary shell command through rtk's
|
|
8
|
+
* output compression. Once rtk ships a native MCP server, this wrapper becomes
|
|
9
|
+
* redundant and rtk can be chained directly like headroom.
|
|
10
|
+
*
|
|
11
|
+
* **Layering — this is NOT the rtk hook.** rtk's own value comes from its
|
|
12
|
+
* PreToolUse hook (installed by `rtk init -g`), which rewrites an agent's Bash
|
|
13
|
+
* calls (`git status` → `rtk git status`) *before* they execute. That hook
|
|
14
|
+
* operates at the agent's shell layer. This MCP wrapper is a *different* layer:
|
|
15
|
+
* it runs rtk as a normal CLI subprocess inside the Adaptive MCP middleware
|
|
16
|
+
* chain, compressing the output of a tool call that already returned. The two
|
|
17
|
+
* compose — the hook compresses what the agent sends to the shell, this wrapper
|
|
18
|
+
* compresses what a tool's MCP result carries back. See `docs/doubts.md` §12b.
|
|
19
|
+
*/
|
|
20
|
+
export declare const RTK_TOOLS: BinaryToolSpec[];
|
|
21
|
+
export interface RtkWrapperOptions {
|
|
22
|
+
/**
|
|
23
|
+
* Path or name of the rtk binary. Defaults to `"rtk"`.
|
|
24
|
+
*
|
|
25
|
+
* If omitted, `resolveRtkCommand()` is used to locate the user's existing
|
|
26
|
+
* install (graceful coexistence — we prefer the binary the user already has
|
|
27
|
+
* and configured over bundling or re-installing one).
|
|
28
|
+
*/
|
|
29
|
+
command?: string;
|
|
30
|
+
version?: string;
|
|
31
|
+
timeoutMs?: number;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* The result of locating the rtk binary on the host.
|
|
35
|
+
*
|
|
36
|
+
* `status` tells the caller how to behave:
|
|
37
|
+
* - `"found"`: a working rtk-ai binary is available — wrap it directly.
|
|
38
|
+
* - `"missing"`: no rtk on PATH — the caller should degrade gracefully
|
|
39
|
+
* (e.g. skip the rtk middleware, or surface a setup hint) rather than
|
|
40
|
+
* spawn a binary that does not exist.
|
|
41
|
+
* - `"wrong-package"`: a binary named `rtk` exists but it is the unrelated
|
|
42
|
+
* Rust *Type Kit* crate from crates.io (its `rtk gain` fails). The caller
|
|
43
|
+
* must NOT treat this as rtk-ai; it should warn and skip.
|
|
44
|
+
*/
|
|
45
|
+
export interface RtkResolution {
|
|
46
|
+
status: "found" | "missing" | "wrong-package";
|
|
47
|
+
/** The command/path to use, when `status === "found"`. */
|
|
48
|
+
command?: string;
|
|
49
|
+
/** Human-readable detail for logs / `contributeView`. */
|
|
50
|
+
detail?: string;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Locate a usable rtk-ai binary on the host.
|
|
54
|
+
*
|
|
55
|
+
* 1. If `command` is an absolute/relative path, verify it exists and that
|
|
56
|
+
* `rtk --version` reports an `rtk <semver>` line (the rtk-ai binary),
|
|
57
|
+
* not the Rust Type Kit crate.
|
|
58
|
+
* 2. Otherwise search `PATH` for `rtk`, then probe it the same way.
|
|
59
|
+
*
|
|
60
|
+
* This is the sanctioned, read-only discovery step. It never downloads or
|
|
61
|
+
* installs anything — Adaptive MCP must not mutate the host's toolchain. If the
|
|
62
|
+
* user already has rtk (from Homebrew, the official installer, or cargo), we
|
|
63
|
+
* reuse it; if not, we report `missing` and let the caller degrade.
|
|
64
|
+
*/
|
|
65
|
+
export declare function resolveRtkCommand(command?: string): RtkResolution;
|
|
66
|
+
/**
|
|
67
|
+
* Build an `BinaryMcpServer` that wraps the rtk CLI. This is the sanctioned
|
|
68
|
+
* shell-out layer (D4/D10): rtk becomes a chainable MCP server instead of
|
|
69
|
+
* living at the host layer or shelling out inside core.
|
|
70
|
+
*
|
|
71
|
+
* Discovery is graceful: when `command` is omitted we resolve the user's
|
|
72
|
+
* existing rtk install via `resolveRtkCommand()`. If none is found (or the
|
|
73
|
+
* `rtk` name collides with another package), the returned server is marked
|
|
74
|
+
* `unavailable` and its `rtk_exec` tool will report a clear setup message
|
|
75
|
+
* instead of spawning a missing binary. Call `server.available` to check.
|
|
76
|
+
*/
|
|
77
|
+
export declare function createRtkWrapper(options?: RtkWrapperOptions): BinaryMcpServer;
|
|
78
|
+
//# sourceMappingURL=rtk.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rtk.d.ts","sourceRoot":"","sources":["../src/rtk.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAA+B,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAEhG;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,SAAS,EAAE,cAAc,EAWrC,CAAC;AAEF,MAAM,WAAW,iBAAiB;IAChC;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,OAAO,GAAG,SAAS,GAAG,eAAe,CAAC;IAC9C,0DAA0D;IAC1D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yDAAyD;IACzD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,aAAa,CAoCjE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,iBAAsB,GAAG,eAAe,CAWjF"}
|
package/dist/rtk.js
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { execFileSync } from "node:child_process";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { BinaryMcpServer } from "./server.js";
|
|
4
|
+
/**
|
|
5
|
+
* Reference binary config for **rtk** (rtk-ai.app).
|
|
6
|
+
*
|
|
7
|
+
* rtk has no native MCP server (doubts.md §12b, issue #1442 is "gauging
|
|
8
|
+
* interest" only), so it is wrapped here into an MCP server. The wrapper exposes
|
|
9
|
+
* a single `rtk_exec` tool that runs an arbitrary shell command through rtk's
|
|
10
|
+
* output compression. Once rtk ships a native MCP server, this wrapper becomes
|
|
11
|
+
* redundant and rtk can be chained directly like headroom.
|
|
12
|
+
*
|
|
13
|
+
* **Layering — this is NOT the rtk hook.** rtk's own value comes from its
|
|
14
|
+
* PreToolUse hook (installed by `rtk init -g`), which rewrites an agent's Bash
|
|
15
|
+
* calls (`git status` → `rtk git status`) *before* they execute. That hook
|
|
16
|
+
* operates at the agent's shell layer. This MCP wrapper is a *different* layer:
|
|
17
|
+
* it runs rtk as a normal CLI subprocess inside the Adaptive MCP middleware
|
|
18
|
+
* chain, compressing the output of a tool call that already returned. The two
|
|
19
|
+
* compose — the hook compresses what the agent sends to the shell, this wrapper
|
|
20
|
+
* compresses what a tool's MCP result carries back. See `docs/doubts.md` §12b.
|
|
21
|
+
*/
|
|
22
|
+
export const RTK_TOOLS = [
|
|
23
|
+
{
|
|
24
|
+
name: "rtk_exec",
|
|
25
|
+
description: "Run a shell command through rtk's CLI-output compression. Returns the compressed command output.",
|
|
26
|
+
subcommand: "gain",
|
|
27
|
+
inputSchema: {
|
|
28
|
+
command: z.string().describe("The shell command to run and compress."),
|
|
29
|
+
},
|
|
30
|
+
argStyle: "positionals",
|
|
31
|
+
},
|
|
32
|
+
];
|
|
33
|
+
/**
|
|
34
|
+
* Locate a usable rtk-ai binary on the host.
|
|
35
|
+
*
|
|
36
|
+
* 1. If `command` is an absolute/relative path, verify it exists and that
|
|
37
|
+
* `rtk --version` reports an `rtk <semver>` line (the rtk-ai binary),
|
|
38
|
+
* not the Rust Type Kit crate.
|
|
39
|
+
* 2. Otherwise search `PATH` for `rtk`, then probe it the same way.
|
|
40
|
+
*
|
|
41
|
+
* This is the sanctioned, read-only discovery step. It never downloads or
|
|
42
|
+
* installs anything — Adaptive MCP must not mutate the host's toolchain. If the
|
|
43
|
+
* user already has rtk (from Homebrew, the official installer, or cargo), we
|
|
44
|
+
* reuse it; if not, we report `missing` and let the caller degrade.
|
|
45
|
+
*/
|
|
46
|
+
export function resolveRtkCommand(command) {
|
|
47
|
+
const candidates = command ? [command] : ["rtk"];
|
|
48
|
+
for (const candidate of candidates) {
|
|
49
|
+
// Probe: rtk-ai prints "rtk <version>"; the Rust Type Kit crate does not.
|
|
50
|
+
// `execFileSync` resolves PATH names itself, so a bare "rtk" works.
|
|
51
|
+
try {
|
|
52
|
+
const out = execFileSync(candidate, ["--version"], {
|
|
53
|
+
encoding: "utf8",
|
|
54
|
+
timeout: 5000,
|
|
55
|
+
windowsHide: true,
|
|
56
|
+
});
|
|
57
|
+
if (/^rtk\s+\d+\.\d+/.test(out.trim())) {
|
|
58
|
+
return { status: "found", command: candidate, detail: out.trim() };
|
|
59
|
+
}
|
|
60
|
+
// A binary named `rtk` exists but is not rtk-ai (name collision).
|
|
61
|
+
return {
|
|
62
|
+
status: "wrong-package",
|
|
63
|
+
detail: `Found a binary named 'rtk' at ${candidate}, but it is not rtk-ai (its --version is "${out.trim()}"). This is likely the unrelated Rust 'Type Kit' crate. Install rtk-ai from https://rtk-ai.app instead.`,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
// Probe failed: not on PATH, not executable, or the wrong package that
|
|
68
|
+
// errors on --version. If an explicit path was given, report it as a
|
|
69
|
+
// collision; otherwise keep looking (PATH name collision).
|
|
70
|
+
if (command) {
|
|
71
|
+
return {
|
|
72
|
+
status: "wrong-package",
|
|
73
|
+
detail: `The binary at '${command}' did not respond to 'rtk --version' like rtk-ai. Verify it is the rtk-ai binary (https://rtk-ai.app).`,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
status: "missing",
|
|
81
|
+
detail: "rtk-ai not found on PATH. Install it from https://rtk-ai.app (or set RtkWrapperOptions.command to an explicit path). The rtk middleware will be skipped.",
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Build an `BinaryMcpServer` that wraps the rtk CLI. This is the sanctioned
|
|
86
|
+
* shell-out layer (D4/D10): rtk becomes a chainable MCP server instead of
|
|
87
|
+
* living at the host layer or shelling out inside core.
|
|
88
|
+
*
|
|
89
|
+
* Discovery is graceful: when `command` is omitted we resolve the user's
|
|
90
|
+
* existing rtk install via `resolveRtkCommand()`. If none is found (or the
|
|
91
|
+
* `rtk` name collides with another package), the returned server is marked
|
|
92
|
+
* `unavailable` and its `rtk_exec` tool will report a clear setup message
|
|
93
|
+
* instead of spawning a missing binary. Call `server.available` to check.
|
|
94
|
+
*/
|
|
95
|
+
export function createRtkWrapper(options = {}) {
|
|
96
|
+
const resolution = resolveRtkCommand(options.command);
|
|
97
|
+
const opts = {
|
|
98
|
+
name: "adaptive-rtk-wrapper",
|
|
99
|
+
version: options.version ?? "0.1.0",
|
|
100
|
+
command: resolution.command ?? "rtk",
|
|
101
|
+
tools: RTK_TOOLS,
|
|
102
|
+
timeoutMs: options.timeoutMs,
|
|
103
|
+
unavailable: resolution.status !== "found" ? resolution.detail : undefined,
|
|
104
|
+
};
|
|
105
|
+
return new BinaryMcpServer(opts);
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=rtk.js.map
|
package/dist/rtk.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rtk.js","sourceRoot":"","sources":["../src/rtk.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,eAAe,EAAoD,MAAM,aAAa,CAAC;AAEhG;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,SAAS,GAAqB;IACzC;QACE,IAAI,EAAE,UAAU;QAChB,WAAW,EACT,kGAAkG;QACpG,UAAU,EAAE,MAAM;QAClB,WAAW,EAAE;YACX,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,wCAAwC,CAAC;SACvE;QACD,QAAQ,EAAE,aAAa;KACxB;CACF,CAAC;AAmCF;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAgB;IAChD,MAAM,UAAU,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IACjD,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,0EAA0E;QAC1E,oEAAoE;QACpE,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,YAAY,CAAC,SAAS,EAAE,CAAC,WAAW,CAAC,EAAE;gBACjD,QAAQ,EAAE,MAAM;gBAChB,OAAO,EAAE,IAAI;gBACb,WAAW,EAAE,IAAI;aAClB,CAAC,CAAC;YACH,IAAI,iBAAiB,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;gBACvC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC;YACrE,CAAC;YACD,kEAAkE;YAClE,OAAO;gBACL,MAAM,EAAE,eAAe;gBACvB,MAAM,EAAE,iCAAiC,SAAS,6CAA6C,GAAG,CAAC,IAAI,EAAE,yGAAyG;aACnN,CAAC;QACJ,CAAC;QAAC,MAAM,CAAC;YACP,uEAAuE;YACvE,qEAAqE;YACrE,2DAA2D;YAC3D,IAAI,OAAO,EAAE,CAAC;gBACZ,OAAO;oBACL,MAAM,EAAE,eAAe;oBACvB,MAAM,EAAE,kBAAkB,OAAO,wGAAwG;iBAC1I,CAAC;YACJ,CAAC;YACD,SAAS;QACX,CAAC;IACH,CAAC;IACD,OAAO;QACL,MAAM,EAAE,SAAS;QACjB,MAAM,EAAE,0JAA0J;KACnK,CAAC;AACJ,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,gBAAgB,CAAC,UAA6B,EAAE;IAC9D,MAAM,UAAU,GAAG,iBAAiB,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACtD,MAAM,IAAI,GAA2B;QACnC,IAAI,EAAE,sBAAsB;QAC5B,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,OAAO;QACnC,OAAO,EAAE,UAAU,CAAC,OAAO,IAAI,KAAK;QACpC,KAAK,EAAE,SAAS;QAChB,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,WAAW,EAAE,UAAU,CAAC,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;KAC3E,CAAC;IACF,OAAO,IAAI,eAAe,CAAC,IAAI,CAAC,CAAC;AACnC,CAAC"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* A single CLI subcommand exposed as an MCP tool.
|
|
4
|
+
*
|
|
5
|
+
* The wrapper shells out to `<command> <subcommand> [args...]` and returns the
|
|
6
|
+
* combined stdout/stderr as the tool result. This is the **only** place in
|
|
7
|
+
* Adaptive MCP permitted to spawn processes (doubts.md §12b / D10) — it is the
|
|
8
|
+
* sanctioned shell-out layer that lets binaries like rtk become chainable MCP
|
|
9
|
+
* servers instead of living at the host layer or shelling out inside core.
|
|
10
|
+
*/
|
|
11
|
+
export interface BinaryToolSpec {
|
|
12
|
+
/** MCP tool name, e.g. `rtk_exec`. */
|
|
13
|
+
name: string;
|
|
14
|
+
/** Human description shown in `tools/list`. */
|
|
15
|
+
description: string;
|
|
16
|
+
/** The subcommand passed to the binary (e.g. `gain`, `compress`). */
|
|
17
|
+
subcommand: string;
|
|
18
|
+
/**
|
|
19
|
+
* Zod-validated input schema for the tool. The parsed args are forwarded to
|
|
20
|
+
* the binary as CLI flags/positionals. Use `argStyle` to control formatting.
|
|
21
|
+
*/
|
|
22
|
+
inputSchema: z.ZodRawShape;
|
|
23
|
+
/** How to render parsed args on the command line. Defaults to `--key value`. */
|
|
24
|
+
argStyle?: "flags" | "positionals";
|
|
25
|
+
}
|
|
26
|
+
export interface BinaryMcpServerOptions {
|
|
27
|
+
/** Server identity advertised in `initialize`. */
|
|
28
|
+
name: string;
|
|
29
|
+
version?: string;
|
|
30
|
+
/** The binary to invoke, e.g. `"rtk"` or `"/usr/local/bin/rtk"`. */
|
|
31
|
+
command: string;
|
|
32
|
+
/** Base args always prepended (e.g. `["--json"]`). */
|
|
33
|
+
baseArgs?: string[];
|
|
34
|
+
/** Tools to expose. */
|
|
35
|
+
tools: BinaryToolSpec[];
|
|
36
|
+
/** Shell out timeout in ms (per invocation). Defaults to 30s. */
|
|
37
|
+
timeoutMs?: number;
|
|
38
|
+
/**
|
|
39
|
+
* When set, the binary could not be located/verified (e.g. rtk not installed,
|
|
40
|
+
* or the `rtk` name collides with another package). The server still registers
|
|
41
|
+
* its tools, but each invocation returns this message instead of spawning a
|
|
42
|
+
* missing binary. Lets the chain degrade gracefully rather than erroring.
|
|
43
|
+
*/
|
|
44
|
+
unavailable?: string;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Wraps a CLI binary into an MCP stdio server. Each `BinaryToolSpec` becomes an
|
|
48
|
+
* MCP tool that runs `<command> <subcommand> <args>` and returns the output.
|
|
49
|
+
*
|
|
50
|
+
* This is intentionally generic (D10): rtk is the reference binary, but any
|
|
51
|
+
* CLI tool whose output benefits from in-loop transformation can be wrapped the
|
|
52
|
+
* same way and then chained through `@adaptivemcp/middleware`.
|
|
53
|
+
*/
|
|
54
|
+
export declare class BinaryMcpServer {
|
|
55
|
+
private server;
|
|
56
|
+
private opts;
|
|
57
|
+
constructor(options: BinaryMcpServerOptions);
|
|
58
|
+
private registerTool;
|
|
59
|
+
/** Whether the wrapped binary was located and verified at construction. */
|
|
60
|
+
get available(): boolean;
|
|
61
|
+
/** Server identity advertised in `initialize`. */
|
|
62
|
+
get name(): string;
|
|
63
|
+
/** Server version advertised in `initialize`. */
|
|
64
|
+
get version(): string;
|
|
65
|
+
/** Names of the tools registered on this server. */
|
|
66
|
+
toolNames(): string[];
|
|
67
|
+
/** Spawn the binary, write `input` (if any) to stdin, resolve with stdout. */
|
|
68
|
+
private run;
|
|
69
|
+
private renderArgs;
|
|
70
|
+
/** Attach to stdio and start listening. */
|
|
71
|
+
start(): Promise<void>;
|
|
72
|
+
/** Stop the server. */
|
|
73
|
+
close(): Promise<void>;
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;;;GAQG;AACH,MAAM,WAAW,cAAc;IAC7B,sCAAsC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,+CAA+C;IAC/C,WAAW,EAAE,MAAM,CAAC;IACpB,qEAAqE;IACrE,UAAU,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,WAAW,EAAE,CAAC,CAAC,WAAW,CAAC;IAC3B,gFAAgF;IAChF,QAAQ,CAAC,EAAE,OAAO,GAAG,aAAa,CAAC;CACpC;AAED,MAAM,WAAW,sBAAsB;IACrC,kDAAkD;IAClD,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,oEAAoE;IACpE,OAAO,EAAE,MAAM,CAAC;IAChB,sDAAsD;IACtD,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,uBAAuB;IACvB,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,iEAAiE;IACjE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;GAOG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,IAAI,CAAyB;gBAEzB,OAAO,EAAE,sBAAsB;IAW3C,OAAO,CAAC,YAAY;IAuBpB,2EAA2E;IAC3E,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,kDAAkD;IAClD,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,iDAAiD;IACjD,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED,oDAAoD;IACpD,SAAS,IAAI,MAAM,EAAE;IAIrB,8EAA8E;IAC9E,OAAO,CAAC,GAAG;IA+BX,OAAO,CAAC,UAAU;IAYlB,2CAA2C;IACrC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAK5B,uBAAuB;IACjB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7B"}
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
/**
|
|
5
|
+
* Wraps a CLI binary into an MCP stdio server. Each `BinaryToolSpec` becomes an
|
|
6
|
+
* MCP tool that runs `<command> <subcommand> <args>` and returns the output.
|
|
7
|
+
*
|
|
8
|
+
* This is intentionally generic (D10): rtk is the reference binary, but any
|
|
9
|
+
* CLI tool whose output benefits from in-loop transformation can be wrapped the
|
|
10
|
+
* same way and then chained through `@adaptivemcp/middleware`.
|
|
11
|
+
*/
|
|
12
|
+
export class BinaryMcpServer {
|
|
13
|
+
server;
|
|
14
|
+
opts;
|
|
15
|
+
constructor(options) {
|
|
16
|
+
this.opts = options;
|
|
17
|
+
this.server = new McpServer({ name: options.name, version: options.version ?? "0.1.0" }, { capabilities: {} });
|
|
18
|
+
for (const tool of options.tools) {
|
|
19
|
+
this.registerTool(tool);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
registerTool(tool) {
|
|
23
|
+
this.server.registerTool(tool.name, {
|
|
24
|
+
title: tool.name,
|
|
25
|
+
description: tool.description,
|
|
26
|
+
inputSchema: tool.inputSchema,
|
|
27
|
+
}, async (args) => {
|
|
28
|
+
if (this.opts.unavailable) {
|
|
29
|
+
return {
|
|
30
|
+
content: [{ type: "text", text: this.opts.unavailable }],
|
|
31
|
+
isError: true,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
const out = await this.run(tool.subcommand, args, tool.argStyle ?? "flags");
|
|
35
|
+
return {
|
|
36
|
+
content: [{ type: "text", text: out }],
|
|
37
|
+
};
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
/** Whether the wrapped binary was located and verified at construction. */
|
|
41
|
+
get available() {
|
|
42
|
+
return !this.opts.unavailable;
|
|
43
|
+
}
|
|
44
|
+
/** Server identity advertised in `initialize`. */
|
|
45
|
+
get name() {
|
|
46
|
+
return this.opts.name;
|
|
47
|
+
}
|
|
48
|
+
/** Server version advertised in `initialize`. */
|
|
49
|
+
get version() {
|
|
50
|
+
return this.opts.version ?? "0.1.0";
|
|
51
|
+
}
|
|
52
|
+
/** Names of the tools registered on this server. */
|
|
53
|
+
toolNames() {
|
|
54
|
+
return this.opts.tools.map((t) => t.name);
|
|
55
|
+
}
|
|
56
|
+
/** Spawn the binary, write `input` (if any) to stdin, resolve with stdout. */
|
|
57
|
+
run(subcommand, args, style) {
|
|
58
|
+
const cliArgs = [
|
|
59
|
+
...(this.opts.baseArgs ?? []),
|
|
60
|
+
subcommand,
|
|
61
|
+
...this.renderArgs(args, style),
|
|
62
|
+
];
|
|
63
|
+
return new Promise((resolve, reject) => {
|
|
64
|
+
const child = spawn(this.opts.command, cliArgs, {
|
|
65
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
66
|
+
});
|
|
67
|
+
let stdout = "";
|
|
68
|
+
let stderr = "";
|
|
69
|
+
const timer = setTimeout(() => {
|
|
70
|
+
child.kill("SIGKILL");
|
|
71
|
+
reject(new Error(`binary ${this.opts.command} timed out after ${this.opts.timeoutMs ?? 30000}ms`));
|
|
72
|
+
}, this.opts.timeoutMs ?? 30000);
|
|
73
|
+
child.stdout.on("data", (d) => (stdout += d.toString()));
|
|
74
|
+
child.stderr.on("data", (d) => (stderr += d.toString()));
|
|
75
|
+
child.on("error", (err) => {
|
|
76
|
+
clearTimeout(timer);
|
|
77
|
+
reject(err);
|
|
78
|
+
});
|
|
79
|
+
child.on("close", (code) => {
|
|
80
|
+
clearTimeout(timer);
|
|
81
|
+
if (code === 0)
|
|
82
|
+
resolve(stdout.trim());
|
|
83
|
+
else
|
|
84
|
+
reject(new Error(`${this.opts.command} exited ${code}: ${stderr.trim() || stdout.trim()}`));
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
renderArgs(args, style) {
|
|
89
|
+
if (style === "positionals") {
|
|
90
|
+
return Object.values(args).map(String);
|
|
91
|
+
}
|
|
92
|
+
const out = [];
|
|
93
|
+
for (const [key, value] of Object.entries(args)) {
|
|
94
|
+
if (value === undefined || value === null)
|
|
95
|
+
continue;
|
|
96
|
+
out.push(`--${key}`, String(value));
|
|
97
|
+
}
|
|
98
|
+
return out;
|
|
99
|
+
}
|
|
100
|
+
/** Attach to stdio and start listening. */
|
|
101
|
+
async start() {
|
|
102
|
+
const transport = new StdioServerTransport();
|
|
103
|
+
await this.server.connect(transport);
|
|
104
|
+
}
|
|
105
|
+
/** Stop the server. */
|
|
106
|
+
async close() {
|
|
107
|
+
await this.server.close();
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAuC,MAAM,oBAAoB,CAAC;AAChF,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAiDjF;;;;;;;GAOG;AACH,MAAM,OAAO,eAAe;IAClB,MAAM,CAAY;IAClB,IAAI,CAAyB;IAErC,YAAY,OAA+B;QACzC,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC;QACpB,IAAI,CAAC,MAAM,GAAG,IAAI,SAAS,CACzB,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,OAAO,EAAE,EAC3D,EAAE,YAAY,EAAE,EAAE,EAAE,CACrB,CAAC;QACF,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YACjC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAEO,YAAY,CAAC,IAAoB;QACvC,IAAI,CAAC,MAAM,CAAC,YAAY,CACtB,IAAI,CAAC,IAAI,EACT;YACE,KAAK,EAAE,IAAI,CAAC,IAAI;YAChB,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,WAAW,EAAE,IAAI,CAAC,WAAW;SAC9B,EACD,KAAK,EAAE,IAA6B,EAAE,EAAE;YACtC,IAAI,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;gBAC1B,OAAO;oBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;oBACxD,OAAO,EAAE,IAAI;iBACd,CAAC;YACJ,CAAC;YACD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,IAAI,OAAO,CAAC,CAAC;YAC5E,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;aACvC,CAAC;QACJ,CAAC,CACF,CAAC;IACJ,CAAC;IAED,2EAA2E;IAC3E,IAAI,SAAS;QACX,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC;IAChC,CAAC;IAED,kDAAkD;IAClD,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;IACxB,CAAC;IAED,iDAAiD;IACjD,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC;IACtC,CAAC;IAED,oDAAoD;IACpD,SAAS;QACP,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAC5C,CAAC;IAED,8EAA8E;IACtE,GAAG,CAAC,UAAkB,EAAE,IAA6B,EAAE,KAA8B;QAC3F,MAAM,OAAO,GAAG;YACd,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC;YAC7B,UAAU;YACV,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,KAAK,CAAC;SAChC,CAAC;QACF,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,MAAM,KAAK,GAAmC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE;gBAC9E,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;aAChC,CAAC,CAAC;YACH,IAAI,MAAM,GAAG,EAAE,CAAC;YAChB,IAAI,MAAM,GAAG,EAAE,CAAC;YAChB,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;gBAC5B,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;gBACtB,MAAM,CAAC,IAAI,KAAK,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC,OAAO,oBAAoB,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC;YACrG,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,KAAK,CAAC,CAAC;YAEjC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;YACzD,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;YACzD,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;gBACxB,YAAY,CAAC,KAAK,CAAC,CAAC;gBACpB,MAAM,CAAC,GAAG,CAAC,CAAC;YACd,CAAC,CAAC,CAAC;YACH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;gBACzB,YAAY,CAAC,KAAK,CAAC,CAAC;gBACpB,IAAI,IAAI,KAAK,CAAC;oBAAE,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;;oBAClC,MAAM,CAAC,IAAI,KAAK,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,WAAW,IAAI,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;YACnG,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,UAAU,CAAC,IAA6B,EAAE,KAA8B;QAC9E,IAAI,KAAK,KAAK,aAAa,EAAE,CAAC;YAC5B,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACzC,CAAC;QACD,MAAM,GAAG,GAAa,EAAE,CAAC;QACzB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YAChD,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;gBAAE,SAAS;YACpD,GAAG,CAAC,IAAI,CAAC,KAAK,GAAG,EAAE,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QACtC,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAED,2CAA2C;IAC3C,KAAK,CAAC,KAAK;QACT,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;QAC7C,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACvC,CAAC;IAED,uBAAuB;IACvB,KAAK,CAAC,KAAK;QACT,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;IAC5B,CAAC;CACF"}
|
package/package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@adaptivemcp/mcp-binary",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Generic CLI-binary -> MCP-server stdio wrapper (the only sanctioned shell-out layer).",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"README.md"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsc -p tsconfig.json",
|
|
21
|
+
"test": "vitest run --config ../../vitest.config.ts"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"@adaptivemcp/spec": "workspace:*",
|
|
25
|
+
"@modelcontextprotocol/sdk": "^1.30.1",
|
|
26
|
+
"zod": "^4.0.0"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"typescript": "^5.6.0",
|
|
30
|
+
"vitest": "^2.1.0"
|
|
31
|
+
}
|
|
32
|
+
}
|