toolcraft 0.0.8 → 0.0.9

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/dist/cli.js CHANGED
@@ -714,20 +714,36 @@ function formatSecretDescription(secret) {
714
714
  }
715
715
  return secret.optional === true ? "Optional secret" : "Required secret";
716
716
  }
717
- function formatCommandRowName(node, depth) {
718
- const name = node.aliases.length === 0 ? node.name : `${node.name} (${node.aliases.join(", ")})`;
717
+ function wrapOptionalCommandParameterToken(token, optional) {
718
+ return optional ? `[${token}]` : token;
719
+ }
720
+ function formatCommandDynamicParameterTokens(field, casing) {
721
+ const optional = field.optional || field.hasDefault;
722
+ return formatDynamicHelpFields(field, casing).map((row) => wrapOptionalCommandParameterToken(row.flags, optional));
723
+ }
724
+ function formatCommandParameterTokens(command, casing, globalLongOptionFlags) {
725
+ const collected = collectFields(command.params, casing, globalLongOptionFlags);
726
+ const fields = assignPositionals(collected.fields, command.positional);
727
+ return fields
728
+ .map((field) => wrapOptionalCommandParameterToken(formatHelpFieldFlags(field, globalLongOptionFlags), field.positionalIndex === undefined && (field.optional || field.hasDefault)))
729
+ .concat(collected.dynamicFields.flatMap((field) => formatCommandDynamicParameterTokens(field, casing)));
730
+ }
731
+ function formatCommandRowName(node, depth, casing, globalLongOptionFlags) {
732
+ const baseName = node.aliases.length === 0 ? node.name : `${node.name} (${node.aliases.join(", ")})`;
733
+ const parameterTokens = node.kind === "command" ? formatCommandParameterTokens(node, casing, globalLongOptionFlags) : [];
734
+ const name = parameterTokens.length === 0 ? baseName : `${baseName} ${parameterTokens.join(" ")}`;
719
735
  return `${" ".repeat(depth)}${name}`;
720
736
  }
721
- function formatCommandRows(group, scope, depth = 0) {
737
+ function formatCommandRows(group, scope, casing, globalLongOptionFlags, depth = 0) {
722
738
  return getVisibleChildren(group, scope).flatMap((child) => {
723
739
  const row = {
724
- name: formatCommandRowName(child, depth),
740
+ name: formatCommandRowName(child, depth, casing, globalLongOptionFlags),
725
741
  description: child.description ?? "",
726
742
  };
727
743
  if (child.kind === "command") {
728
744
  return [row];
729
745
  }
730
- return [row, ...formatCommandRows(child, scope, depth + 1)];
746
+ return [row, ...formatCommandRows(child, scope, casing, globalLongOptionFlags, depth + 1)];
731
747
  });
732
748
  }
733
749
  function formatGlobalOptionRows(showVersion, presetsEnabled) {
@@ -766,9 +782,10 @@ function buildUsageLine(breadcrumb, rootUsageName, suffix) {
766
782
  const subPath = breadcrumb.slice(1).join(" ");
767
783
  return subPath ? `${rootUsageName} ${subPath} ${suffix}` : `${rootUsageName} ${suffix}`;
768
784
  }
769
- function renderGroupHelp(group, breadcrumb, scope, showVersion, presetsEnabled, rootUsageName) {
785
+ function renderGroupHelp(group, breadcrumb, scope, casing, showVersion, presetsEnabled, rootUsageName) {
770
786
  const sections = [];
771
- const commandRows = formatCommandRows(group, scope);
787
+ const globalLongOptionFlags = getGlobalLongOptionFlags(presetsEnabled);
788
+ const commandRows = formatCommandRows(group, scope, casing, globalLongOptionFlags);
772
789
  if (commandRows.length > 0) {
773
790
  sections.push(`${text.section("Commands:")}\n${formatCommandList(commandRows)}`);
774
791
  }
@@ -833,7 +850,7 @@ async function renderGeneratedHelp(root, argv, options) {
833
850
  const casing = options.casing ?? "kebab";
834
851
  await withOutputFormat(output, async () => {
835
852
  const rendered = target.node.kind === "group"
836
- ? renderGroupHelp(target.node, target.breadcrumb, "cli", options.version !== undefined, options.presets === true, options.rootUsageName)
853
+ ? renderGroupHelp(target.node, target.breadcrumb, "cli", casing, options.version !== undefined, options.presets === true, options.rootUsageName)
837
854
  : renderLeafHelp(target.node, target.breadcrumb, casing, options.presets === true, options.rootUsageName);
838
855
  process.stdout.write(rendered);
839
856
  });
@@ -0,0 +1,97 @@
1
+ # tiny-mcp-client
2
+
3
+ `tiny-mcp-client` is a lightweight Model Context Protocol client used by tests, fixtures, and package integrations. It supports stdio transports, streamable HTTP transports, in-memory test pairs, JSON-RPC helpers, and OAuth metadata discovery for OAuth-protected MCP HTTP servers.
4
+
5
+ ## Usage
6
+
7
+ ```ts
8
+ import { HttpTransport, McpClient } from "tiny-mcp-client";
9
+
10
+ const client = new McpClient({
11
+ clientInfo: { name: "demo", version: "0.1.0" },
12
+ });
13
+
14
+ await client.connect(new HttpTransport({ url: "http://127.0.0.1:3000/mcp" }));
15
+ const tools = await client.listTools();
16
+ console.log(tools);
17
+ await client.close();
18
+ ```
19
+
20
+ ## Transports
21
+
22
+ | Transport | Description |
23
+ |-----------|-------------|
24
+ | `StdioTransport` | Spawns an MCP server process and communicates over stdio. |
25
+ | `HttpTransport` | Connects to streamable HTTP MCP endpoints, including session IDs, SSE GET streams, and session termination. |
26
+ | `createInMemoryTransportPair()` | Creates paired streams for in-process tests. |
27
+
28
+ ## OAuth HTTP support
29
+
30
+ `HttpTransport` accepts `oauth` options from `mcp-oauth`. When a protected server returns a Bearer `WWW-Authenticate` challenge, the transport discovers protected-resource metadata, loads authorization-server metadata, lets the OAuth provider handle authorization, and retries the request when credentials are available.
31
+
32
+ ```ts
33
+ import { HttpTransport, createDefaultOAuthClientProvider } from "tiny-mcp-client";
34
+
35
+ const transport = new HttpTransport({
36
+ url: "https://mcp.example.com/mcp",
37
+ oauth: {
38
+ provider: createDefaultOAuthClientProvider({
39
+ client: {
40
+ mode: "dynamic",
41
+ metadata: {
42
+ clientName: "tiny-client",
43
+ },
44
+ },
45
+ browser: {
46
+ openBrowser: async (url) => {
47
+ console.log(`Open ${url}`);
48
+ },
49
+ },
50
+ }),
51
+ },
52
+ });
53
+ ```
54
+
55
+ You can also call `discoverOAuthMetadata(resourceUrl, options)` directly, or instantiate `OAuthMetadataDiscovery` with a custom `fetch` implementation and shared cache.
56
+
57
+ ## Testing helpers
58
+
59
+ - `createTestPair()` and `createSdkTestPair()` create paired client/server fixtures.
60
+ - `createInMemoryTransportPair()` is useful for fast unit tests without opening sockets or spawning processes.
61
+ - JSON-RPC error constants are exported for assertions: `ERROR_PARSE`, `ERROR_INVALID_REQUEST`, `ERROR_METHOD_NOT_FOUND`, `ERROR_INVALID_PARAMS`, and `ERROR_INTERNAL`.
62
+
63
+ ## Config options
64
+
65
+ ### `McpClientOptions`
66
+
67
+ | Option | Type | Description |
68
+ |--------|------|-------------|
69
+ | `clientInfo` | `{ name: string; version: string }` | Required client identity sent during initialize. |
70
+ | `capabilities` | `ClientCapabilities` | Optional MCP client capabilities. |
71
+ | `onToolsChanged`, `onResourcesChanged`, `onPromptsChanged` | callbacks | Optional notification handlers. |
72
+ | `onResourceUpdated`, `onLog`, `onProgress` | callbacks | Optional resource/log/progress handlers. |
73
+ | `onSamplingRequest`, `onRootsList` | callbacks | Optional server-to-client request handlers. |
74
+
75
+ ### `HttpTransportOptions`
76
+
77
+ | Option | Type | Description |
78
+ |--------|------|-------------|
79
+ | `url` | `string` | MCP HTTP endpoint URL. |
80
+ | `headers` | `HeadersInit` | Static headers added to requests. |
81
+ | `fetch` | `(input, init?) => Promise<Response>` | Custom fetch implementation. |
82
+ | `oauth` | `OAuthClientProviderOptions` | Enables OAuth authorization handling. |
83
+ | `oauthDiscoveryCache` | `OAuthDiscoveryCache` | Optional shared metadata cache. |
84
+
85
+ ### `StdioTransportOptions`
86
+
87
+ | Option | Type | Description |
88
+ |--------|------|-------------|
89
+ | `command` | `string` | Server executable. |
90
+ | `args` | `string[]` | Server args. |
91
+ | `cwd` | `string` | Server working directory. |
92
+ | `env` | `NodeJS.ProcessEnv` | Server environment. |
93
+ | `spawn` | `StdioSpawn` | Custom spawn function for tests. |
94
+
95
+ ## Environment variables
96
+
97
+ This package does not expose public environment variables. Pass process environment explicitly through `StdioTransportOptions.env` when a spawned MCP server needs it.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toolcraft",
3
- "version": "0.0.8",
3
+ "version": "0.0.9",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -45,7 +45,7 @@
45
45
  "commander": "^14.0.3",
46
46
  "console-table-printer": "^2.15.0",
47
47
  "tiny-stdio-mcp-server": "^0.1.0",
48
- "toolcraft-schema": "^0.0.8"
48
+ "toolcraft-schema": "^0.0.9"
49
49
  },
50
50
  "files": [
51
51
  "dist"