@procedures/mcp-dev-tools 0.7.0 → 0.8.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 CHANGED
@@ -1,5 +1,54 @@
1
1
  # @procedures/mcp-dev-tools
2
2
 
3
+ ## 0.8.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 2523b1b: One MCP host factory, `createMcpHost()`, and the questions of a procedure to the person at the caller (CLI-10, CLI-12). PATCH: new exports and new optional options before 1.0.0. The old exports and their behavior stay.
8
+
9
+ - `@procedures/mcp-server`: `createMcpHost(options)` builds the registry (or the modules), the tool surface, the read-only narrowing, the host policy, the `ProcedureServer` and one `McpServerTransport` for each face (stdio, Streamable HTTP, SDK transports). The stdio face stops the host when its input ends, and `host.closed` resolves. `mcp.serve` and the dev-tools server use the factory. Thus `mcp.serve` gets its options from `hostPolicy()`, and it takes `readOnly` and `instructions`.
10
+ - `@procedures/client`: `ctx.elicit` asks the person at the caller for input or a confirmation. The helpers `elicitInput()` and `elicitConfirmation()` give the action `unavailable` with a reason when no one can answer. `elicitWithPolicy()` adds the consents of the operator (`operatorConsent`), and `ask: false` turns the questions off. The operator answers only when the face cannot ask. A failed question of a face that can ask (a timeout, a lost connection) gives `unavailable`, and an abort gives `cancel`. `ServerRequest` and `InvokeOptions` get `elicit` and `progress`.
11
+ - `@procedures/client`: `ctx.progress` tells the caller the progress of the call of the host. `metadata.untrusted` declares the output fields with text from outside the host, and `metadata.title` gives the title of a tool. `metadata.toolHints` can make a tool look more dangerous than its effects (`readOnlyHint: false`, `idempotentHint: false`, `destructiveHint: true`, `openWorldHint: true`). The registry refuses each other value, and `toolHintsOf()` gives the hints with the override.
12
+ - `@procedures/mcp-server`: `McpServerTransport` answers `ctx.elicit` with MCP elicitation (form and URL), over stdio and Streamable HTTP. It sends `ctx.progress` as `notifications/progress`, and it gives the instructions of the server. An untrusted field goes in envelopes with a random id, and its text cannot close its envelope. The option `content` can give other text blocks for a result. The option `json: "compact"` gives the JSON of the default blocks on one line. The option `toolName` gives the name of each tool, so a server that moves to the host keeps its tool names. A call finds its procedure by the tool, not by the decoded name. Each tool call over Streamable HTTP carries the credentials of its HTTP request, so the request hook `principalOf` and the token check of the server apply to it. A server that reads cookies gets the CSRF rule on this face too.
13
+ - `@procedures/mcp`: a tool gets `title` from `metadata.title`. In the output schema, each untrusted field is a string.
14
+ - `@procedures/mcp-dev-tools`: `createDevToolsHost()` gives the MCP host as `mcp`. `dist/server.js` ends its process when the client closes the input of stdio. The tool list stays the same.
15
+ - Updated dependencies [2d3f235]
16
+ - Updated dependencies [1aa9ef7]
17
+ - Updated dependencies [2523b1b]
18
+ - Updated dependencies [c559b00]
19
+ - @procedures/client@0.8.1
20
+ - @procedures/mcp-server@0.8.1
21
+ - @procedures/bundle-mcp@0.8.1
22
+ - @procedures/fs@0.8.1
23
+ - @procedures/compiler@0.8.1
24
+
25
+ ## 0.8.0
26
+
27
+ ### Minor Changes
28
+
29
+ - 3f376af: The root of the files confines each procedure, not only `fs.*` (roadmap R33). `mark --fs-root`, `procedure-server --fs-root` and `MCP_FS_ROOT` start `confineToRoot()` of `@procedures/fs`. Each procedure keeps its paths in the root, or the host refuses it with `FORBIDDEN` and the reason `outside-root`.
30
+
31
+ This change is breaking under a root. The hosts refuse procedures that they ran before: `git.*`, `pnpm.*`, `docker.run`, `docker.build`, `docker.compose.*`, a call of `shell.run`, and each procedure that reaches files without `metadata.fsRoot`. `lib.scan` of a workspace outside the root gives `FORBIDDEN`, not a warning. Without a root, nothing changes. The list of the MCP tools does not change.
32
+
33
+ ### Patch Changes
34
+
35
+ - Updated dependencies [4b09a03]
36
+ - Updated dependencies [4b09a03]
37
+ - Updated dependencies [aa6e3aa]
38
+ - Updated dependencies [698e24d]
39
+ - Updated dependencies [4b09a03]
40
+ - Updated dependencies [600c497]
41
+ - Updated dependencies [7c2e7f7]
42
+ - Updated dependencies [90ea741]
43
+ - Updated dependencies [90ea741]
44
+ - Updated dependencies [c4cfa34]
45
+ - Updated dependencies [d25805a]
46
+ - @procedures/client@0.8.0
47
+ - @procedures/fs@0.8.0
48
+ - @procedures/bundle-mcp@0.8.0
49
+ - @procedures/mcp-server@0.8.0
50
+ - @procedures/compiler@0.8.0
51
+
3
52
  ## 0.7.0
4
53
 
5
54
  ### Patch Changes
package/README.md CHANGED
@@ -33,6 +33,8 @@ The package has the bin `mcp-dev-tools`, which starts the same file.
33
33
 
34
34
  Claude Code starts the server once for each session. After a rebuild, restart the MCP server (or the session) to get the changes.
35
35
 
36
+ When the client closes the input of stdio, the server stops: the calls in flight get their grace time, and then the process ends.
37
+
36
38
  ## Configuration
37
39
 
38
40
  | Environment variable | Default | Function |
@@ -45,30 +47,37 @@ Claude Code starts the server once for each session. After a rebuild, restart th
45
47
  | `MCP_READ_ONLY` | `false` | With `true`, the tools are only the procedures that change nothing |
46
48
  | `MCP_HTTP_PORT`, `MCP_HTTP_HOST`, `MCP_HTTP_TOKEN` | not set | The server uses Streamable HTTP on this port, not stdio. The host is `127.0.0.1` by default. |
47
49
  | `MCP_PROGRAM_CHECK` | `true` | With `false`, a program starts without the check before the run |
48
- | `MCP_FS_ROOT` | not set | The folder that confines each path of the `fs.*` procedures. Refer to "The root of the file procedures". |
50
+ | `MCP_FS_ROOT` | not set | The root of the files: each tool keeps its paths in this folder, or the host refuses it. Refer to "The root of the files". |
49
51
 
50
52
  `mark mcp` starts the same server. Its flags replace the variables: `--bundles`, `--tool-timeout`, `--read-only`, `--http`, `--host`, `--token` and `--fs-root`.
51
53
 
52
54
  The server serves no remote events (`documentation/EVENTS.md`). Its transport carries only MCP, and `events.subscribe` is not a tool. Thus the host has no variable for the topics.
53
55
 
54
- ## The root of the file procedures
56
+ ## The root of the files
55
57
 
56
- With `MCP_FS_ROOT` (or `mark mcp --fs-root <folder>`), the host confines each path of the `fs.*` procedures to the folder (roadmap R33):
58
+ With `MCP_FS_ROOT` (or `mark mcp --fs-root <folder>`), the host confines each tool to the folder (roadmap R33):
57
59
 
58
- - The host starts `confineFsProcedures()` of `@procedures/fs` after it builds its registry. The function replaces the handlers of the `fs.*` procedures, and it adds no procedure.
59
- - `fs` is not a tool namespace, so the tools and `tools.snapshot.txt` do not change. Only the behavior of the tools changes.
60
- - A tool reads files through nested `fs.*` calls, so the root confines these calls too. For example, `lib.scan` of a workspace outside the root gives a warning and no packages.
61
- - A path outside the root gives `FORBIDDEN` with the reason `outside-root`. A relative path starts at the root.
60
+ - The host starts `confineToRoot()` of `@procedures/fs` after it builds its registry. The function replaces handlers, and it adds no procedure.
61
+ - The list of the tools and `tools.snapshot.txt` do not change. The host refuses some tools under a root.
62
+ - A tool keeps its paths in the root. The host examines the path inputs of its rules (`metadata.fsRoot`) before it starts. The nested `fs.*` calls are confined too.
63
+ - A path outside the root gives `FORBIDDEN` with the reason `outside-root`. A relative path starts at the root. A working folder without a value is the root.
64
+ - The host refuses each tool that the root cannot confine, with the same error. At the start, it writes the refused procedures to stderr.
62
65
  - The host does not start when the folder does not exist.
63
66
 
64
- The root does not confine a procedure that reads files with `node:fs`, or that starts a program. In the tools of `bundle-mcp`, these are:
67
+ The tools of `bundle-mcp` under a root:
65
68
 
66
- - `lib.*`: `existsSync` of `pnpm-workspace.yaml`, and the TypeScript files of `lib.rename` (`ts-morph`). The `cue-config` program of `lib.new` writes files too.
67
- - `cue.generate` and `cue.validate`: the `cue` program, and the read of `dependencies.json`.
68
- - `git.*`, `docker.*`, `pnpm.*` and `vitest.*`: their programs. `git.init` also uses `realpath` and `access`, and `vitest.run` reads its JSON report.
69
- - `sqlite.*` and `logs.*`: the database file.
69
+ | Tools | Under a root |
70
+ |---|---|
71
+ | `cue.*` | Confined: `cwd` |
72
+ | `lib.scan`, `lib.graph`, `lib.audit`, `lib.rename` | Confined: `rootPath`. Their nested git calls are refused, and `lib.scan` gives a warning. |
73
+ | `procedure.new` | Confined: `path` |
74
+ | `sqlite.*`, `logs.*` | Confined: `dbPath`, which a call must give, or `:memory:` |
75
+ | `docker.ps`, `docker.logs`, `docker.stop`, `docker.rm`, `docker.images`, `docker.inspect`, `docker.pull`, `docker.tag`, `docker.volume.*`, `docker.network.*` | Confined: `cwd`. Docker runs in a folder of the root. |
76
+ | `docker.run`, `docker.exec`, `docker.build`, `docker.compose.*` | Refused: a volume, a compose file or a Dockerfile reaches host folders, or runs a program |
77
+ | `lib.new`, `vitest.run`, `vitest.coverage` | Refused: they start code of the project |
78
+ | `client.*`, `json.*`, `yaml.*`, `mongo.*`, `program.*`, the other `procedure.*` tools | Unchanged: they reach no file |
70
79
 
71
- `cue.init`, `cue.add`, `cue.remove` and `procedure.new` use only `fs.*`, so the root confines them completely. Each `cue.*` procedure except `cue.remove` reads `features.json` of the installed `@mark1russell7/cue` through `fs.read`. Thus they fail when that package is outside the root.
80
+ The rules and the table of all the procedures are in [CAPABILITIES-2026-10.md](../documentation/CAPABILITIES-2026-10.md#the-root-of-the-files-roadmap-r33).
72
81
 
73
82
  ## How it selects the tools
74
83
 
@@ -76,6 +85,7 @@ The root does not confine a procedure that reads files with `node:fs`, or that s
76
85
  2. A procedure is a tool when its namespace is in `mcpNamespaces` of a bundle, and its key is not in `mcpExclude`.
77
86
  3. A `ProcedureServer` serves the registry with that rule as its `expose` rule. A data-driven procedure (`client.chain`, `client.eval`, a procedure of `procedure.define`) can use only exposed procedures.
78
87
  4. `McpServerTransport` gives the exposed procedures as tools over stdio. It tells Claude when the list of tools changes.
88
+ `createMcpHost()` of `@procedures/mcp-server` builds the host: the same factory as `mcp.serve` and the MCP hosts of the apps.
79
89
  5. The host checks the program of each call to a data-driven procedure before the first step (`programCheckInterceptor` of `@procedures/compiler`). When the check finds an error, no step starts. Thus a refusal in step 3 comes before the write of step 1.
80
90
 
81
91
  > [!WARNING]