toolfunnel 0.4.0 → 0.6.0

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 (78) hide show
  1. package/README.md +102 -213
  2. package/bin/toolfunnel.js +372 -147
  3. package/docs/KNOWN_BUGS.md +99 -225
  4. package/docs/MANUAL.pdf +0 -0
  5. package/docs/design.md +70 -0
  6. package/docs/packaging.md +115 -115
  7. package/hooks/hooks.manifest.json +27 -27
  8. package/hooks/scripts/example-audit.js +21 -21
  9. package/hooks/scripts/example-deny-dangerous.js +31 -31
  10. package/mcp/expose.example.json +30 -30
  11. package/mcp/servers/mock-modern/server.js +147 -0
  12. package/mcp/servers/mock-upstream/server.js +192 -12
  13. package/package.json +1 -1
  14. package/src/auth/config.js +174 -174
  15. package/src/auth/install.js +181 -181
  16. package/src/auth/resource-server.js +344 -344
  17. package/src/core/config-home.js +134 -134
  18. package/src/core/events.js +105 -105
  19. package/src/core/hook-engine.js +275 -275
  20. package/src/core/hook-loader.js +791 -791
  21. package/src/core/hook-runner.js +346 -346
  22. package/src/core/logger.js +171 -171
  23. package/src/core/matcher.js +51 -51
  24. package/src/core/metrics.js +75 -75
  25. package/src/core/requires.js +138 -138
  26. package/src/core/server-config.js +98 -77
  27. package/src/core/tool-registry.js +180 -180
  28. package/src/extend/add-hook.md +152 -142
  29. package/src/extend/add-mcp.md +122 -121
  30. package/src/extend/configure.md +87 -0
  31. package/src/extend/create-tool.md +168 -152
  32. package/src/extend/howto.js +102 -98
  33. package/src/extend/package.md +187 -187
  34. package/src/extend/wrap.md +99 -0
  35. package/src/mcp/aggregator.js +1246 -807
  36. package/src/mcp/expose-store.js +460 -430
  37. package/src/mcp/gated-run.js +201 -194
  38. package/src/mcp/http-transport.js +1311 -981
  39. package/src/mcp/mcp-client.js +907 -530
  40. package/src/mcp/modern.js +372 -0
  41. package/src/mcp/protocol.js +468 -466
  42. package/src/mcp/server.js +2688 -1322
  43. package/src/packages/packager.js +715 -715
  44. package/src/tools/drift.js +138 -138
  45. package/src/tools/registry.js +513 -511
  46. package/src/tools/tool-state.js +170 -104
  47. package/src/ui/public/app.js +1174 -1055
  48. package/src/ui/public/index.html +286 -249
  49. package/src/ui/public/styles.css +535 -535
  50. package/src/ui/server.js +1348 -1190
  51. package/tools/scripts/base64.js +139 -139
  52. package/tools/scripts/danger.js +61 -61
  53. package/tools/scripts/echo.js +39 -39
  54. package/tools/scripts/hash.js +101 -101
  55. package/tools/scripts/json.js +109 -109
  56. package/tools/scripts/text-stats.js +131 -131
  57. package/tools/scripts/tf-env.js +43 -43
  58. package/tools/scripts/tf-hook-add.js +151 -151
  59. package/tools/scripts/tf-hook-set.js +112 -112
  60. package/tools/scripts/tf-list.js +192 -192
  61. package/tools/scripts/tf-log.js +86 -86
  62. package/tools/scripts/tf-mcp-add.js +117 -117
  63. package/tools/scripts/tf-mcp-set.js +121 -102
  64. package/tools/scripts/tf-pack.js +237 -237
  65. package/tools/scripts/tf-tool-add.js +134 -129
  66. package/tools/scripts/tf-tool-set.js +142 -142
  67. package/tools/scripts/tf-wrap.js +103 -0
  68. package/tools/scripts/uuid.js +102 -102
  69. package/tools/tools.register.json +227 -216
  70. package/docs/admin-ui.md +0 -404
  71. package/docs/configuration.md +0 -402
  72. package/docs/hooks-and-gating.md +0 -428
  73. package/docs/logging.md +0 -223
  74. package/docs/management.md +0 -429
  75. package/docs/oauth.md +0 -103
  76. package/docs/releasing.md +0 -31
  77. package/docs/setup.md +0 -352
  78. package/docs/tools-and-upstreams.md +0 -469
@@ -1,102 +1,102 @@
1
- #!/usr/bin/env node
2
- 'use strict';
3
-
4
- /**
5
- * uuid-tool.js — a safe, dependency-free local UUID generator.
6
- *
7
- * Purpose
8
- * -------
9
- * Generate one or more RFC 4122 v4 UUIDs via the Node built-in
10
- * `node:crypto.randomUUID()`. Useful from the Tool Manager whenever a fresh
11
- * identifier is needed. No network, no filesystem, no new deps.
12
- *
13
- * Contract with the register (the register's `defaultRunScript`)
14
- * ----------------------------------------------------------
15
- * - Structured args arrive as JSON in env TOOLFUNNEL_TOOL_ARGS.
16
- * - Args: { count?: <integer> } — how many UUIDs to mint. Defaults to 1.
17
- * count is clamped to the range [1, 100] so a runaway request cannot ask
18
- * for an unbounded number.
19
- * - Prints a SINGLE JSON object to stdout and exits 0 — ALWAYS exit 0, even
20
- * on bad input (reported as { ok:false, error }), never a thrown exception.
21
- *
22
- * Output (stdout), exactly one JSON object:
23
- * success: { ok:true, uuids: [ "...", ... ] }
24
- * failure: { ok:false, error }
25
- *
26
- * Safety invariants (mirror the isolation rule):
27
- * - NO filesystem, NO network, NO process mutation. Pure CPU on the args.
28
- * - count is hard-capped at 100; a non-integer / out-of-range count is an
29
- * error rather than a silent surprise.
30
- * - NEVER throws for ordinary bad input — only well-shaped JSON on stdout.
31
- */
32
-
33
- const crypto = require('node:crypto');
34
-
35
- const MAX_COUNT = 100;
36
-
37
- /**
38
- * Parse the structured args handed in via env TOOLFUNNEL_TOOL_ARGS.
39
- * @returns {{ value: any } | { parseError: string }}
40
- */
41
- function parseStructuredArgs() {
42
- const raw = process.env.TOOLFUNNEL_TOOL_ARGS;
43
- if (raw === undefined || raw === null || raw === '') {
44
- return { value: null };
45
- }
46
- try {
47
- return { value: JSON.parse(raw) };
48
- } catch (_err) {
49
- return { parseError: `TOOLFUNNEL_TOOL_ARGS was not valid JSON: ${String(raw)}` };
50
- }
51
- }
52
-
53
- /**
54
- * Pure core: given the parsed args, produce the result object. Never throws.
55
- *
56
- * @param {any} args may be null (treated as { count: 1 })
57
- * @returns {object} the JSON-serialisable result
58
- */
59
- function run(args) {
60
- // No args (or null) is valid — default to a single UUID.
61
- let count = 1;
62
- if (args !== null && args !== undefined) {
63
- if (typeof args !== 'object' || Array.isArray(args)) {
64
- return { ok: false, error: 'args must be an object { count? }' };
65
- }
66
- if (args.count !== undefined && args.count !== null) {
67
- if (typeof args.count !== 'number' || !Number.isInteger(args.count)) {
68
- return { ok: false, error: 'count must be an integer' };
69
- }
70
- if (args.count < 1) {
71
- return { ok: false, error: 'count must be >= 1' };
72
- }
73
- if (args.count > MAX_COUNT) {
74
- return { ok: false, error: `count must be <= ${MAX_COUNT}` };
75
- }
76
- count = args.count;
77
- }
78
- }
79
- const uuids = [];
80
- for (let i = 0; i < count; i += 1) {
81
- uuids.push(crypto.randomUUID());
82
- }
83
- return { ok: true, uuids };
84
- }
85
-
86
- function main() {
87
- const parsed = parseStructuredArgs();
88
- let payload;
89
- if (parsed.parseError) {
90
- payload = { ok: false, error: parsed.parseError };
91
- } else {
92
- try {
93
- payload = run(parsed.value);
94
- } catch (err) {
95
- payload = { ok: false, error: `unexpected error: ${(err && err.message) || String(err)}` };
96
- }
97
- }
98
- process.stdout.write(JSON.stringify(payload) + '\n');
99
- process.exit(0);
100
- }
101
-
102
- main();
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /**
5
+ * uuid-tool.js - a safe, dependency-free local UUID generator.
6
+ *
7
+ * Purpose
8
+ * -------
9
+ * Generate one or more RFC 4122 v4 UUIDs via the Node built-in
10
+ * `node:crypto.randomUUID()`. Useful from the Tool Manager whenever a fresh
11
+ * identifier is needed. No network, no filesystem, no new deps.
12
+ *
13
+ * Contract with the register (the register's `defaultRunScript`)
14
+ * ----------------------------------------------------------
15
+ * - Structured args arrive as JSON in env TOOLFUNNEL_TOOL_ARGS.
16
+ * - Args: { count?: <integer> } - how many UUIDs to mint. Defaults to 1.
17
+ * count is clamped to the range [1, 100] so a runaway request cannot ask
18
+ * for an unbounded number.
19
+ * - Prints a SINGLE JSON object to stdout and exits 0 - ALWAYS exit 0, even
20
+ * on bad input (reported as { ok:false, error }), never a thrown exception.
21
+ *
22
+ * Output (stdout), exactly one JSON object:
23
+ * success: { ok:true, uuids: [ "...", ... ] }
24
+ * failure: { ok:false, error }
25
+ *
26
+ * Safety invariants (mirror the isolation rule):
27
+ * - NO filesystem, NO network, NO process mutation. Pure CPU on the args.
28
+ * - count is hard-capped at 100; a non-integer / out-of-range count is an
29
+ * error rather than a silent surprise.
30
+ * - NEVER throws for ordinary bad input - only well-shaped JSON on stdout.
31
+ */
32
+
33
+ const crypto = require('node:crypto');
34
+
35
+ const MAX_COUNT = 100;
36
+
37
+ /**
38
+ * Parse the structured args handed in via env TOOLFUNNEL_TOOL_ARGS.
39
+ * @returns {{ value: any } | { parseError: string }}
40
+ */
41
+ function parseStructuredArgs() {
42
+ const raw = process.env.TOOLFUNNEL_TOOL_ARGS;
43
+ if (raw === undefined || raw === null || raw === '') {
44
+ return { value: null };
45
+ }
46
+ try {
47
+ return { value: JSON.parse(raw) };
48
+ } catch (_err) {
49
+ return { parseError: `TOOLFUNNEL_TOOL_ARGS was not valid JSON: ${String(raw)}` };
50
+ }
51
+ }
52
+
53
+ /**
54
+ * Pure core: given the parsed args, produce the result object. Never throws.
55
+ *
56
+ * @param {any} args may be null (treated as { count: 1 })
57
+ * @returns {object} the JSON-serialisable result
58
+ */
59
+ function run(args) {
60
+ // No args (or null) is valid - default to a single UUID.
61
+ let count = 1;
62
+ if (args !== null && args !== undefined) {
63
+ if (typeof args !== 'object' || Array.isArray(args)) {
64
+ return { ok: false, error: 'args must be an object { count? }' };
65
+ }
66
+ if (args.count !== undefined && args.count !== null) {
67
+ if (typeof args.count !== 'number' || !Number.isInteger(args.count)) {
68
+ return { ok: false, error: 'count must be an integer' };
69
+ }
70
+ if (args.count < 1) {
71
+ return { ok: false, error: 'count must be >= 1' };
72
+ }
73
+ if (args.count > MAX_COUNT) {
74
+ return { ok: false, error: `count must be <= ${MAX_COUNT}` };
75
+ }
76
+ count = args.count;
77
+ }
78
+ }
79
+ const uuids = [];
80
+ for (let i = 0; i < count; i += 1) {
81
+ uuids.push(crypto.randomUUID());
82
+ }
83
+ return { ok: true, uuids };
84
+ }
85
+
86
+ function main() {
87
+ const parsed = parseStructuredArgs();
88
+ let payload;
89
+ if (parsed.parseError) {
90
+ payload = { ok: false, error: parsed.parseError };
91
+ } else {
92
+ try {
93
+ payload = run(parsed.value);
94
+ } catch (err) {
95
+ payload = { ok: false, error: `unexpected error: ${(err && err.message) || String(err)}` };
96
+ }
97
+ }
98
+ process.stdout.write(JSON.stringify(payload) + '\n');
99
+ process.exit(0);
100
+ }
101
+
102
+ main();