@procedures/mcp-dev-tools 0.13.2 → 0.14.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/CHANGELOG.md +43 -0
- package/README.md +6 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/host.d.ts +38 -4
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +74 -8
- package/dist/host.js.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -3
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts +3 -2
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +5 -9
- package/dist/server.js.map +1 -1
- package/package.json +7 -6
- package/src/host.ts +91 -8
- package/src/index.ts +6 -2
- package/src/server.ts +8 -12
package/dist/host.d.ts
CHANGED
|
@@ -7,9 +7,10 @@
|
|
|
7
7
|
* - `strictCalls`: a procedure of code that declares no nested calls calls only tools;
|
|
8
8
|
* - each tool call has a time limit.
|
|
9
9
|
*
|
|
10
|
-
* `server.ts` (the file in the MCP configuration of Claude Code) and `mark mcp` both
|
|
11
|
-
* server with `
|
|
12
|
-
* `@procedures/mcp-server` (CLI-10): the same factory as
|
|
10
|
+
* `server.ts` (the file in the MCP configuration of Claude Code) and `mark mcp` both run the
|
|
11
|
+
* server with `runDevToolsServer()`, under `run()` of `@mark1russell7/service` (CLI-11). The host
|
|
12
|
+
* comes from `createMcpHost()` of `@procedures/mcp-server` (CLI-10): the same factory as
|
|
13
|
+
* `mcp.serve` and the hosts of the apps.
|
|
13
14
|
*
|
|
14
15
|
* `MCP_FS_ROOT` confines the procedures to one folder (`confineToRoot()` of `@procedures/fs`):
|
|
15
16
|
* each tool keeps its paths in it, or the root refuses the tool. The host serves no remote
|
|
@@ -17,6 +18,7 @@
|
|
|
17
18
|
*/
|
|
18
19
|
import { ProcedureServer, type HostPolicy, type ProcedureModule, type ProcedureRegistry, type ToolSurface } from "@procedures/client";
|
|
19
20
|
import { type BundleSurfaceModule, type McpHost } from "@procedures/mcp-server";
|
|
21
|
+
import { type Lifecycle, type RunOptions, type ServiceBuilder } from "@mark1russell7/service";
|
|
20
22
|
import { type McpServerConfig } from "./config.js";
|
|
21
23
|
/** The modules and the tool lists of some bundles. */
|
|
22
24
|
export interface LoadedBundles {
|
|
@@ -43,13 +45,45 @@ export interface DevToolsHost {
|
|
|
43
45
|
/** The MCP host: `mcp.start()` starts its face (stdio, or Streamable HTTP with `config.http`). */
|
|
44
46
|
mcp: McpHost;
|
|
45
47
|
}
|
|
48
|
+
/** The options of `createDevToolsHost()`. */
|
|
49
|
+
export interface DevToolsHostOptions {
|
|
50
|
+
/**
|
|
51
|
+
* True: the HTTP face has no listener of its own, and the caller mounts `mcp.handleHttp` on a
|
|
52
|
+
* listener. `runDevToolsServer()` gives true. The default is false, the listener of the face.
|
|
53
|
+
*/
|
|
54
|
+
mountHttp?: boolean | undefined;
|
|
55
|
+
}
|
|
46
56
|
/** This function builds the host. It starts no transport. */
|
|
47
|
-
export declare function createDevToolsHost(config?: McpServerConfig): Promise<DevToolsHost>;
|
|
57
|
+
export declare function createDevToolsHost(config?: McpServerConfig, options?: DevToolsHostOptions): Promise<DevToolsHost>;
|
|
58
|
+
/** A dev-tools server that runs under `run()`: the host, its service, the lifecycle and the URL of HTTP. */
|
|
59
|
+
export interface RunningDevToolsServer {
|
|
60
|
+
readonly host: DevToolsHost;
|
|
61
|
+
readonly service: ServiceBuilder;
|
|
62
|
+
/** The lifecycle: `life.done` resolves with the exit code after the stop. */
|
|
63
|
+
readonly life: Lifecycle;
|
|
64
|
+
/** The URL of the Streamable HTTP endpoint, with `config.http`. */
|
|
65
|
+
readonly url?: string | undefined;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* This function runs the dev-tools MCP server under `run()` of `@mark1russell7/service` (CLI-11).
|
|
69
|
+
* The runner owns the signals, the stop in stages and the exit of the process.
|
|
70
|
+
*
|
|
71
|
+
* - Over stdio, the profile is `ephemeral`, and the end of the input is the trigger `stdin-close`.
|
|
72
|
+
* stdout carries the protocol, so `console.log` goes to stderr from here on (BUGS-2026-07 Bug5).
|
|
73
|
+
* - With `config.http`, the profile is `localDev`. An `httpTransport` of the service listens on the
|
|
74
|
+
* port, and the Streamable HTTP face mounts on it at `/mcp`. The address is loopback by default.
|
|
75
|
+
*
|
|
76
|
+
* After a startup that failed, `life.errors` tells why, and the process exits with the code 1.
|
|
77
|
+
*/
|
|
78
|
+
export declare function runDevToolsServer(config?: McpServerConfig, run?: RunOptions): Promise<RunningDevToolsServer>;
|
|
48
79
|
/**
|
|
49
80
|
* This function starts the dev-tools MCP server over stdio, or over Streamable HTTP with
|
|
50
81
|
* `config.http` (roadmap R26). Over stdio, stdout carries the protocol, so `console.log` goes to
|
|
51
82
|
* stderr from here on (BUGS-2026-07 Bug5). The stdio server stops when the client closes its
|
|
52
83
|
* input: `host.mcp.closed` then resolves.
|
|
84
|
+
*
|
|
85
|
+
* @deprecated Use `runDevToolsServer()`: it runs the server under `run()` of the service, with a
|
|
86
|
+
* listener of the service for HTTP. The next MINOR removes this function (CLI-11).
|
|
53
87
|
*/
|
|
54
88
|
export declare function startDevToolsServer(config?: McpServerConfig): Promise<DevToolsHost>;
|
|
55
89
|
//# sourceMappingURL=host.d.ts.map
|
package/dist/host.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../src/host.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../src/host.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAEL,eAAe,EAGf,KAAK,UAAU,EACf,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,WAAW,EACjB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAIL,KAAK,mBAAmB,EACxB,KAAK,OAAO,EAEb,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EAAgC,KAAK,SAAS,EAAgB,KAAK,UAAU,EAAE,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAE1I,OAAO,EAAc,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAQ/D,sDAAsD;AACtD,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,QAAQ,EAAE,mBAAmB,EAAE,CAAC;IAChC;;;OAGG;IACH,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,kFAAkF;AAClF,wBAAsB,WAAW,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,aAAa,CAAC,CAgBpF;AAaD,kFAAkF;AAClF,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,OAAO,EAAE,WAAW,GAAG,SAAS,CAAC;IACjC,MAAM,EAAE,UAAU,CAAC;IACnB,MAAM,EAAE,eAAe,CAAC;IACxB,gFAAgF;IAChF,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,6FAA6F;IAC7F,gBAAgB,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IACxC,kGAAkG;IAClG,GAAG,EAAE,OAAO,CAAC;CACd;AAkBD,6CAA6C;AAC7C,MAAM,WAAW,mBAAmB;IAClC;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACjC;AAED,6DAA6D;AAC7D,wBAAsB,kBAAkB,CAAC,MAAM,GAAE,eAA8B,EAAE,OAAO,GAAE,mBAAwB,GAAG,OAAO,CAAC,YAAY,CAAC,CAmCzI;AASD,4GAA4G;AAC5G,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IACjC,6EAA6E;IAC7E,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,mEAAmE;IACnE,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACnC;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,iBAAiB,CAAC,MAAM,GAAE,eAA8B,EAAE,GAAG,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAiChI;AAED;;;;;;;;GAQG;AACH,wBAAsB,mBAAmB,CAAC,MAAM,GAAE,eAA8B,GAAG,OAAO,CAAC,YAAY,CAAC,CAoBvG"}
|
package/dist/host.js
CHANGED
|
@@ -7,9 +7,10 @@
|
|
|
7
7
|
* - `strictCalls`: a procedure of code that declares no nested calls calls only tools;
|
|
8
8
|
* - each tool call has a time limit.
|
|
9
9
|
*
|
|
10
|
-
* `server.ts` (the file in the MCP configuration of Claude Code) and `mark mcp` both
|
|
11
|
-
* server with `
|
|
12
|
-
* `@procedures/mcp-server` (CLI-10): the same factory as
|
|
10
|
+
* `server.ts` (the file in the MCP configuration of Claude Code) and `mark mcp` both run the
|
|
11
|
+
* server with `runDevToolsServer()`, under `run()` of `@mark1russell7/service` (CLI-11). The host
|
|
12
|
+
* comes from `createMcpHost()` of `@procedures/mcp-server` (CLI-10): the same factory as
|
|
13
|
+
* `mcp.serve` and the hosts of the apps.
|
|
13
14
|
*
|
|
14
15
|
* `MCP_FS_ROOT` confines the procedures to one folder (`confineToRoot()` of `@procedures/fs`):
|
|
15
16
|
* each tool keeps its paths in it, or the root refuses the tool. The host serves no remote
|
|
@@ -18,8 +19,11 @@
|
|
|
18
19
|
import { PROCEDURE_REGISTRY, ProcedureServer, createRegistry, registerClientProcedures, } from "@procedures/client";
|
|
19
20
|
import { createMcpHost, mergeSurfaces, redirectConsoleToStderr, } from "@procedures/mcp-server";
|
|
20
21
|
import { programCheckInterceptor } from "@procedures/compiler";
|
|
22
|
+
import { createServer } from "node:http";
|
|
23
|
+
import { ephemeral, localDev, service } from "@mark1russell7/service";
|
|
24
|
+
import { httpTransport } from "@mark1russell7/service/http";
|
|
21
25
|
import { loadConfig } from "./config.js";
|
|
22
|
-
import { ms } from "@procedures/client";
|
|
26
|
+
import { ms, seconds } from "@procedures/client";
|
|
23
27
|
/** This function loads the module entry of each bundle (it registers nothing). */
|
|
24
28
|
export async function loadBundles(bundles) {
|
|
25
29
|
const modules = [];
|
|
@@ -50,10 +54,15 @@ async function loadBundlesGlobally(bundles) {
|
|
|
50
54
|
}
|
|
51
55
|
return { modules: [], surfaces, global: true };
|
|
52
56
|
}
|
|
53
|
-
/**
|
|
54
|
-
|
|
57
|
+
/**
|
|
58
|
+
* The face of the configuration: Streamable HTTP with `config.http`, else stdio. With `mount`, the
|
|
59
|
+
* HTTP face has no listener of its own: the listener of the service answers for it (CLI-11).
|
|
60
|
+
*/
|
|
61
|
+
function facesOf(config, mount) {
|
|
55
62
|
if (!config.http)
|
|
56
63
|
return { stdio: true };
|
|
64
|
+
if (mount)
|
|
65
|
+
return { http: { mount: true, ...(config.http.token ? { token: config.http.token } : {}) } };
|
|
57
66
|
return {
|
|
58
67
|
http: {
|
|
59
68
|
port: config.http.port,
|
|
@@ -63,7 +72,7 @@ function facesOf(config) {
|
|
|
63
72
|
};
|
|
64
73
|
}
|
|
65
74
|
/** This function builds the host. It starts no transport. */
|
|
66
|
-
export async function createDevToolsHost(config = loadConfig()) {
|
|
75
|
+
export async function createDevToolsHost(config = loadConfig(), options = {}) {
|
|
67
76
|
const loaded = await loadBundles(config.bundles);
|
|
68
77
|
const registry = loaded.global ? PROCEDURE_REGISTRY : createRegistry(...loaded.modules);
|
|
69
78
|
// MCP_FS_ROOT (roadmap R33): each procedure of the registry keeps its paths in the root, also
|
|
@@ -88,7 +97,7 @@ export async function createDevToolsHost(config = loadConfig()) {
|
|
|
88
97
|
name: config.serverName,
|
|
89
98
|
version: config.serverVersion,
|
|
90
99
|
debug: config.debug,
|
|
91
|
-
faces: facesOf(config),
|
|
100
|
+
faces: facesOf(config, options.mountHttp === true),
|
|
92
101
|
});
|
|
93
102
|
return {
|
|
94
103
|
registry,
|
|
@@ -99,11 +108,68 @@ export async function createDevToolsHost(config = loadConfig()) {
|
|
|
99
108
|
...(fsRoot !== undefined ? { fsRoot, refusedUnderRoot } : {}),
|
|
100
109
|
};
|
|
101
110
|
}
|
|
111
|
+
/** The knobs of the HTTP listener on the computer of a developer, as data (as the procedures host gives them). */
|
|
112
|
+
const LISTENER_KNOBS = Object.freeze({
|
|
113
|
+
server_idle_close: seconds(5),
|
|
114
|
+
server_idle_sweep_interval: seconds(1),
|
|
115
|
+
server_retry_after: seconds(1),
|
|
116
|
+
});
|
|
117
|
+
/**
|
|
118
|
+
* This function runs the dev-tools MCP server under `run()` of `@mark1russell7/service` (CLI-11).
|
|
119
|
+
* The runner owns the signals, the stop in stages and the exit of the process.
|
|
120
|
+
*
|
|
121
|
+
* - Over stdio, the profile is `ephemeral`, and the end of the input is the trigger `stdin-close`.
|
|
122
|
+
* stdout carries the protocol, so `console.log` goes to stderr from here on (BUGS-2026-07 Bug5).
|
|
123
|
+
* - With `config.http`, the profile is `localDev`. An `httpTransport` of the service listens on the
|
|
124
|
+
* port, and the Streamable HTTP face mounts on it at `/mcp`. The address is loopback by default.
|
|
125
|
+
*
|
|
126
|
+
* After a startup that failed, `life.errors` tells why, and the process exits with the code 1.
|
|
127
|
+
*/
|
|
128
|
+
export async function runDevToolsServer(config = loadConfig(), run) {
|
|
129
|
+
// Defense-in-depth for the stdio transport: a stray console.log would corrupt the protocol
|
|
130
|
+
redirectConsoleToStderr();
|
|
131
|
+
if (config.debug)
|
|
132
|
+
console.error("[mcp-server] Starting with config:", JSON.stringify(config, null, 2));
|
|
133
|
+
const host = await createDevToolsHost(config, { mountHttp: true });
|
|
134
|
+
const profile = config.http ? localDev : ephemeral;
|
|
135
|
+
const svc = host.mcp.declare(service("mcp-dev-tools").profile(profile));
|
|
136
|
+
// A profile without policies leaves them to the service (as runProcedureHost does)
|
|
137
|
+
if (!profile.readiness)
|
|
138
|
+
svc.readiness({ type: "debounce", interval: seconds(5), failAfter: 3, recoverAfter: 1 });
|
|
139
|
+
if (!profile.liveness)
|
|
140
|
+
svc.liveness({ type: "window", failAfter: seconds(45) });
|
|
141
|
+
if (!profile.startup)
|
|
142
|
+
svc.startup(seconds(30));
|
|
143
|
+
let listener;
|
|
144
|
+
if (config.http) {
|
|
145
|
+
const address = config.http.host ?? "127.0.0.1";
|
|
146
|
+
listener = httpTransport(createServer(), LISTENER_KNOBS, { listen: { port: config.http.port, host: address } });
|
|
147
|
+
listener.mount((req, res) => host.mcp.handleHttp(req, res));
|
|
148
|
+
svc.server("mcp-dev-tools.listen", listener.knobs, listener);
|
|
149
|
+
}
|
|
150
|
+
const life = await svc.run(run);
|
|
151
|
+
const face = host.mcp.state().faces[0];
|
|
152
|
+
if (config.debug)
|
|
153
|
+
console.error(`[mcp-server] Started with ${face?.toolCount ?? 0} tools`);
|
|
154
|
+
if (host.fsRoot !== undefined)
|
|
155
|
+
console.error(`[mcp-server] Each tool refuses a path outside ${host.fsRoot}. Refused under the root: ${String(host.refusedUnderRoot)}`);
|
|
156
|
+
let url;
|
|
157
|
+
const bound = listener?.server.address();
|
|
158
|
+
if (config.http && bound && typeof bound === "object") {
|
|
159
|
+
const shown = bound.address === "0.0.0.0" || bound.address === "::" ? "localhost" : bound.address.includes(":") ? `[${bound.address}]` : bound.address;
|
|
160
|
+
url = `http://${shown}:${bound.port}/mcp`;
|
|
161
|
+
console.error(`[mcp-server] Streamable HTTP at ${url}${config.http.token ? " (send Authorization: Bearer <token>)" : ""}`);
|
|
162
|
+
}
|
|
163
|
+
return { host, service: svc, life, ...(url ? { url } : {}) };
|
|
164
|
+
}
|
|
102
165
|
/**
|
|
103
166
|
* This function starts the dev-tools MCP server over stdio, or over Streamable HTTP with
|
|
104
167
|
* `config.http` (roadmap R26). Over stdio, stdout carries the protocol, so `console.log` goes to
|
|
105
168
|
* stderr from here on (BUGS-2026-07 Bug5). The stdio server stops when the client closes its
|
|
106
169
|
* input: `host.mcp.closed` then resolves.
|
|
170
|
+
*
|
|
171
|
+
* @deprecated Use `runDevToolsServer()`: it runs the server under `run()` of the service, with a
|
|
172
|
+
* listener of the service for HTTP. The next MINOR removes this function (CLI-11).
|
|
107
173
|
*/
|
|
108
174
|
export async function startDevToolsServer(config = loadConfig()) {
|
|
109
175
|
// Defense-in-depth for the stdio transport: a stray console.log (from a procedure handler, a
|
package/dist/host.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"host.js","sourceRoot":"","sources":["../src/host.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"host.js","sourceRoot":"","sources":["../src/host.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
* @procedures/mcp-dev-tools (folder packages/impl-mcp-dev)
|
|
3
3
|
*
|
|
4
4
|
* Ready-to-use MCP server exposing the procedure ecosystem to Claude. Importing this entry
|
|
5
|
-
* starts nothing: `
|
|
6
|
-
* do), and `createDevToolsHost()` builds the host without a
|
|
5
|
+
* starts nothing: `runDevToolsServer()` runs the server under `run()` of the service (as
|
|
6
|
+
* `dist/server.js` and `mark mcp` do), and `createDevToolsHost()` builds the host without a
|
|
7
|
+
* transport. `startDevToolsServer()` is deprecated (CLI-11).
|
|
7
8
|
*/
|
|
8
9
|
export { loadConfig, type McpServerConfig } from "./config.js";
|
|
9
|
-
export { createDevToolsHost, startDevToolsServer, loadBundles, type DevToolsHost, type LoadedBundles, } from "./host.js";
|
|
10
|
+
export { createDevToolsHost, runDevToolsServer, startDevToolsServer, loadBundles, type DevToolsHost, type DevToolsHostOptions, type LoadedBundles, type RunningDevToolsServer, } from "./host.js";
|
|
10
11
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAC/D,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,EACnB,WAAW,EACX,KAAK,YAAY,EACjB,KAAK,mBAAmB,EACxB,KAAK,aAAa,EAClB,KAAK,qBAAqB,GAC3B,MAAM,WAAW,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
* @procedures/mcp-dev-tools (folder packages/impl-mcp-dev)
|
|
3
3
|
*
|
|
4
4
|
* Ready-to-use MCP server exposing the procedure ecosystem to Claude. Importing this entry
|
|
5
|
-
* starts nothing: `
|
|
6
|
-
* do), and `createDevToolsHost()` builds the host without a
|
|
5
|
+
* starts nothing: `runDevToolsServer()` runs the server under `run()` of the service (as
|
|
6
|
+
* `dist/server.js` and `mark mcp` do), and `createDevToolsHost()` builds the host without a
|
|
7
|
+
* transport. `startDevToolsServer()` is deprecated (CLI-11).
|
|
7
8
|
*/
|
|
8
9
|
export { loadConfig } from "./config.js";
|
|
9
|
-
export { createDevToolsHost, startDevToolsServer, loadBundles, } from "./host.js";
|
|
10
|
+
export { createDevToolsHost, runDevToolsServer, startDevToolsServer, loadBundles, } from "./host.js";
|
|
10
11
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,UAAU,EAAwB,MAAM,aAAa,CAAC;AAC/D,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,EACnB,WAAW,GAKZ,MAAM,WAAW,CAAC"}
|
package/dist/server.d.ts
CHANGED
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
* MCP configuration of a client runs this file (`node packages/impl-mcp-dev/dist/server.js`).
|
|
6
6
|
* Configurable via environment variables (see `config.ts`). `mark mcp` starts the same server.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
8
|
+
* The server runs under `run()` of `@mark1russell7/service` (CLI-11). The runner owns the signals,
|
|
9
|
+
* the stop in stages and the exit. When the client closes the input of stdio, the trigger
|
|
10
|
+
* `stdin-close` stops the host (the calls in flight get the drain time), and the process exits.
|
|
10
11
|
*/
|
|
11
12
|
export {};
|
|
12
13
|
//# sourceMappingURL=server.d.ts.map
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG"}
|
package/dist/server.js
CHANGED
|
@@ -5,16 +5,12 @@
|
|
|
5
5
|
* MCP configuration of a client runs this file (`node packages/impl-mcp-dev/dist/server.js`).
|
|
6
6
|
* Configurable via environment variables (see `config.ts`). `mark mcp` starts the same server.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
8
|
+
* The server runs under `run()` of `@mark1russell7/service` (CLI-11). The runner owns the signals,
|
|
9
|
+
* the stop in stages and the exit. When the client closes the input of stdio, the trigger
|
|
10
|
+
* `stdin-close` stops the host (the calls in flight get the drain time), and the process exits.
|
|
10
11
|
*/
|
|
11
|
-
import {
|
|
12
|
-
|
|
13
|
-
.then(async (host) => {
|
|
14
|
-
await host.mcp.closed;
|
|
15
|
-
process.exit(0);
|
|
16
|
-
})
|
|
17
|
-
.catch((error) => {
|
|
12
|
+
import { runDevToolsServer } from "./host.js";
|
|
13
|
+
runDevToolsServer().catch((error) => {
|
|
18
14
|
console.error("[mcp-server] Fatal error:", error);
|
|
19
15
|
process.exit(1);
|
|
20
16
|
});
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAE9C,iBAAiB,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IAClC,OAAO,CAAC,KAAK,CAAC,2BAA2B,EAAE,KAAK,CAAC,CAAC;IAClD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package",
|
|
3
3
|
"name": "@procedures/mcp-dev-tools",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.14.1",
|
|
5
5
|
"description": "A ready-to-use MCP server for Claude Code and Claude Desktop: 91 developer tools (docker, mongo, sqlite, cue, vitest, workspace) with a strict call policy.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"mcp",
|
|
@@ -53,11 +53,12 @@
|
|
|
53
53
|
"provenance": true
|
|
54
54
|
},
|
|
55
55
|
"dependencies": {
|
|
56
|
-
"@
|
|
57
|
-
"@procedures/
|
|
58
|
-
"@procedures/
|
|
59
|
-
"@procedures/
|
|
60
|
-
"@procedures/
|
|
56
|
+
"@mark1russell7/service": "^0.5.2",
|
|
57
|
+
"@procedures/bundle-mcp": "0.14.1",
|
|
58
|
+
"@procedures/client": "0.14.1",
|
|
59
|
+
"@procedures/compiler": "0.14.1",
|
|
60
|
+
"@procedures/fs": "0.14.1",
|
|
61
|
+
"@procedures/mcp-server": "0.14.1"
|
|
61
62
|
},
|
|
62
63
|
"devDependencies": {
|
|
63
64
|
"@mark1russell7/cue": "^1.0.0",
|
package/src/host.ts
CHANGED
|
@@ -7,9 +7,10 @@
|
|
|
7
7
|
* - `strictCalls`: a procedure of code that declares no nested calls calls only tools;
|
|
8
8
|
* - each tool call has a time limit.
|
|
9
9
|
*
|
|
10
|
-
* `server.ts` (the file in the MCP configuration of Claude Code) and `mark mcp` both
|
|
11
|
-
* server with `
|
|
12
|
-
* `@procedures/mcp-server` (CLI-10): the same factory as
|
|
10
|
+
* `server.ts` (the file in the MCP configuration of Claude Code) and `mark mcp` both run the
|
|
11
|
+
* server with `runDevToolsServer()`, under `run()` of `@mark1russell7/service` (CLI-11). The host
|
|
12
|
+
* comes from `createMcpHost()` of `@procedures/mcp-server` (CLI-10): the same factory as
|
|
13
|
+
* `mcp.serve` and the hosts of the apps.
|
|
13
14
|
*
|
|
14
15
|
* `MCP_FS_ROOT` confines the procedures to one folder (`confineToRoot()` of `@procedures/fs`):
|
|
15
16
|
* each tool keeps its paths in it, or the root refuses the tool. The host serves no remote
|
|
@@ -35,8 +36,11 @@ import {
|
|
|
35
36
|
type McpHostFaces,
|
|
36
37
|
} from "@procedures/mcp-server";
|
|
37
38
|
import { programCheckInterceptor } from "@procedures/compiler";
|
|
39
|
+
import { createServer } from "node:http";
|
|
40
|
+
import { ephemeral, localDev, service, type Lifecycle, type Profile, type RunOptions, type ServiceBuilder } from "@mark1russell7/service";
|
|
41
|
+
import { httpTransport, type HttpKnobs, type HttpTransport } from "@mark1russell7/service/http";
|
|
38
42
|
import { loadConfig, type McpServerConfig } from "./config.js";
|
|
39
|
-
import { ms } from "@procedures/client";
|
|
43
|
+
import { ms, seconds } from "@procedures/client";
|
|
40
44
|
|
|
41
45
|
/** The exports of a bundle's `module` entry: its module and the lists of its tools. */
|
|
42
46
|
interface BundleModuleExports extends BundleSurfaceModule {
|
|
@@ -98,9 +102,13 @@ export interface DevToolsHost {
|
|
|
98
102
|
mcp: McpHost;
|
|
99
103
|
}
|
|
100
104
|
|
|
101
|
-
/**
|
|
102
|
-
|
|
105
|
+
/**
|
|
106
|
+
* The face of the configuration: Streamable HTTP with `config.http`, else stdio. With `mount`, the
|
|
107
|
+
* HTTP face has no listener of its own: the listener of the service answers for it (CLI-11).
|
|
108
|
+
*/
|
|
109
|
+
function facesOf(config: McpServerConfig, mount: boolean): McpHostFaces {
|
|
103
110
|
if (!config.http) return { stdio: true };
|
|
111
|
+
if (mount) return { http: { mount: true, ...(config.http.token ? { token: config.http.token } : {}) } };
|
|
104
112
|
return {
|
|
105
113
|
http: {
|
|
106
114
|
port: config.http.port,
|
|
@@ -110,8 +118,17 @@ function facesOf(config: McpServerConfig): McpHostFaces {
|
|
|
110
118
|
};
|
|
111
119
|
}
|
|
112
120
|
|
|
121
|
+
/** The options of `createDevToolsHost()`. */
|
|
122
|
+
export interface DevToolsHostOptions {
|
|
123
|
+
/**
|
|
124
|
+
* True: the HTTP face has no listener of its own, and the caller mounts `mcp.handleHttp` on a
|
|
125
|
+
* listener. `runDevToolsServer()` gives true. The default is false, the listener of the face.
|
|
126
|
+
*/
|
|
127
|
+
mountHttp?: boolean | undefined;
|
|
128
|
+
}
|
|
129
|
+
|
|
113
130
|
/** This function builds the host. It starts no transport. */
|
|
114
|
-
export async function createDevToolsHost(config: McpServerConfig = loadConfig()): Promise<DevToolsHost> {
|
|
131
|
+
export async function createDevToolsHost(config: McpServerConfig = loadConfig(), options: DevToolsHostOptions = {}): Promise<DevToolsHost> {
|
|
115
132
|
const loaded = await loadBundles(config.bundles);
|
|
116
133
|
const registry = loaded.global ? PROCEDURE_REGISTRY : createRegistry(...loaded.modules);
|
|
117
134
|
// MCP_FS_ROOT (roadmap R33): each procedure of the registry keeps its paths in the root, also
|
|
@@ -136,7 +153,7 @@ export async function createDevToolsHost(config: McpServerConfig = loadConfig())
|
|
|
136
153
|
name: config.serverName,
|
|
137
154
|
version: config.serverVersion,
|
|
138
155
|
debug: config.debug,
|
|
139
|
-
faces: facesOf(config),
|
|
156
|
+
faces: facesOf(config, options.mountHttp === true),
|
|
140
157
|
});
|
|
141
158
|
return {
|
|
142
159
|
registry,
|
|
@@ -148,11 +165,77 @@ export async function createDevToolsHost(config: McpServerConfig = loadConfig())
|
|
|
148
165
|
};
|
|
149
166
|
}
|
|
150
167
|
|
|
168
|
+
/** The knobs of the HTTP listener on the computer of a developer, as data (as the procedures host gives them). */
|
|
169
|
+
const LISTENER_KNOBS: HttpKnobs = Object.freeze({
|
|
170
|
+
server_idle_close: seconds(5),
|
|
171
|
+
server_idle_sweep_interval: seconds(1),
|
|
172
|
+
server_retry_after: seconds(1),
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
/** A dev-tools server that runs under `run()`: the host, its service, the lifecycle and the URL of HTTP. */
|
|
176
|
+
export interface RunningDevToolsServer {
|
|
177
|
+
readonly host: DevToolsHost;
|
|
178
|
+
readonly service: ServiceBuilder;
|
|
179
|
+
/** The lifecycle: `life.done` resolves with the exit code after the stop. */
|
|
180
|
+
readonly life: Lifecycle;
|
|
181
|
+
/** The URL of the Streamable HTTP endpoint, with `config.http`. */
|
|
182
|
+
readonly url?: string | undefined;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* This function runs the dev-tools MCP server under `run()` of `@mark1russell7/service` (CLI-11).
|
|
187
|
+
* The runner owns the signals, the stop in stages and the exit of the process.
|
|
188
|
+
*
|
|
189
|
+
* - Over stdio, the profile is `ephemeral`, and the end of the input is the trigger `stdin-close`.
|
|
190
|
+
* stdout carries the protocol, so `console.log` goes to stderr from here on (BUGS-2026-07 Bug5).
|
|
191
|
+
* - With `config.http`, the profile is `localDev`. An `httpTransport` of the service listens on the
|
|
192
|
+
* port, and the Streamable HTTP face mounts on it at `/mcp`. The address is loopback by default.
|
|
193
|
+
*
|
|
194
|
+
* After a startup that failed, `life.errors` tells why, and the process exits with the code 1.
|
|
195
|
+
*/
|
|
196
|
+
export async function runDevToolsServer(config: McpServerConfig = loadConfig(), run?: RunOptions): Promise<RunningDevToolsServer> {
|
|
197
|
+
// Defense-in-depth for the stdio transport: a stray console.log would corrupt the protocol
|
|
198
|
+
redirectConsoleToStderr();
|
|
199
|
+
if (config.debug) console.error("[mcp-server] Starting with config:", JSON.stringify(config, null, 2));
|
|
200
|
+
|
|
201
|
+
const host = await createDevToolsHost(config, { mountHttp: true });
|
|
202
|
+
const profile: Profile = config.http ? localDev : ephemeral;
|
|
203
|
+
const svc = host.mcp.declare(service("mcp-dev-tools").profile(profile));
|
|
204
|
+
// A profile without policies leaves them to the service (as runProcedureHost does)
|
|
205
|
+
if (!profile.readiness) svc.readiness({ type: "debounce", interval: seconds(5), failAfter: 3, recoverAfter: 1 });
|
|
206
|
+
if (!profile.liveness) svc.liveness({ type: "window", failAfter: seconds(45) });
|
|
207
|
+
if (!profile.startup) svc.startup(seconds(30));
|
|
208
|
+
|
|
209
|
+
let listener: HttpTransport | undefined;
|
|
210
|
+
if (config.http) {
|
|
211
|
+
const address = config.http.host ?? "127.0.0.1";
|
|
212
|
+
listener = httpTransport(createServer(), LISTENER_KNOBS, { listen: { port: config.http.port, host: address } });
|
|
213
|
+
listener.mount((req, res) => host.mcp.handleHttp(req, res));
|
|
214
|
+
svc.server("mcp-dev-tools.listen", listener.knobs, listener);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const life = await svc.run(run);
|
|
218
|
+
const face = host.mcp.state().faces[0];
|
|
219
|
+
if (config.debug) console.error(`[mcp-server] Started with ${face?.toolCount ?? 0} tools`);
|
|
220
|
+
if (host.fsRoot !== undefined) console.error(`[mcp-server] Each tool refuses a path outside ${host.fsRoot}. Refused under the root: ${String(host.refusedUnderRoot)}`);
|
|
221
|
+
let url: string | undefined;
|
|
222
|
+
const bound = listener?.server.address();
|
|
223
|
+
if (config.http && bound && typeof bound === "object") {
|
|
224
|
+
const shown = bound.address === "0.0.0.0" || bound.address === "::" ? "localhost" : bound.address.includes(":") ? `[${bound.address}]` : bound.address;
|
|
225
|
+
url = `http://${shown}:${bound.port}/mcp`;
|
|
226
|
+
console.error(`[mcp-server] Streamable HTTP at ${url}${config.http.token ? " (send Authorization: Bearer <token>)" : ""}`);
|
|
227
|
+
}
|
|
228
|
+
return { host, service: svc, life, ...(url ? { url } : {}) };
|
|
229
|
+
}
|
|
230
|
+
|
|
151
231
|
/**
|
|
152
232
|
* This function starts the dev-tools MCP server over stdio, or over Streamable HTTP with
|
|
153
233
|
* `config.http` (roadmap R26). Over stdio, stdout carries the protocol, so `console.log` goes to
|
|
154
234
|
* stderr from here on (BUGS-2026-07 Bug5). The stdio server stops when the client closes its
|
|
155
235
|
* input: `host.mcp.closed` then resolves.
|
|
236
|
+
*
|
|
237
|
+
* @deprecated Use `runDevToolsServer()`: it runs the server under `run()` of the service, with a
|
|
238
|
+
* listener of the service for HTTP. The next MINOR removes this function (CLI-11).
|
|
156
239
|
*/
|
|
157
240
|
export async function startDevToolsServer(config: McpServerConfig = loadConfig()): Promise<DevToolsHost> {
|
|
158
241
|
// Defense-in-depth for the stdio transport: a stray console.log (from a procedure handler, a
|
package/src/index.ts
CHANGED
|
@@ -2,15 +2,19 @@
|
|
|
2
2
|
* @procedures/mcp-dev-tools (folder packages/impl-mcp-dev)
|
|
3
3
|
*
|
|
4
4
|
* Ready-to-use MCP server exposing the procedure ecosystem to Claude. Importing this entry
|
|
5
|
-
* starts nothing: `
|
|
6
|
-
* do), and `createDevToolsHost()` builds the host without a
|
|
5
|
+
* starts nothing: `runDevToolsServer()` runs the server under `run()` of the service (as
|
|
6
|
+
* `dist/server.js` and `mark mcp` do), and `createDevToolsHost()` builds the host without a
|
|
7
|
+
* transport. `startDevToolsServer()` is deprecated (CLI-11).
|
|
7
8
|
*/
|
|
8
9
|
|
|
9
10
|
export { loadConfig, type McpServerConfig } from "./config.js";
|
|
10
11
|
export {
|
|
11
12
|
createDevToolsHost,
|
|
13
|
+
runDevToolsServer,
|
|
12
14
|
startDevToolsServer,
|
|
13
15
|
loadBundles,
|
|
14
16
|
type DevToolsHost,
|
|
17
|
+
type DevToolsHostOptions,
|
|
15
18
|
type LoadedBundles,
|
|
19
|
+
type RunningDevToolsServer,
|
|
16
20
|
} from "./host.js";
|
package/src/server.ts
CHANGED
|
@@ -5,18 +5,14 @@
|
|
|
5
5
|
* MCP configuration of a client runs this file (`node packages/impl-mcp-dev/dist/server.js`).
|
|
6
6
|
* Configurable via environment variables (see `config.ts`). `mark mcp` starts the same server.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
8
|
+
* The server runs under `run()` of `@mark1russell7/service` (CLI-11). The runner owns the signals,
|
|
9
|
+
* the stop in stages and the exit. When the client closes the input of stdio, the trigger
|
|
10
|
+
* `stdin-close` stops the host (the calls in flight get the drain time), and the process exits.
|
|
10
11
|
*/
|
|
11
12
|
|
|
12
|
-
import {
|
|
13
|
+
import { runDevToolsServer } from "./host.js";
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
.
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
})
|
|
19
|
-
.catch((error) => {
|
|
20
|
-
console.error("[mcp-server] Fatal error:", error);
|
|
21
|
-
process.exit(1);
|
|
22
|
-
});
|
|
15
|
+
runDevToolsServer().catch((error) => {
|
|
16
|
+
console.error("[mcp-server] Fatal error:", error);
|
|
17
|
+
process.exit(1);
|
|
18
|
+
});
|