@miragon/mcp-toolkit-tool-codegen 0.10.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 +41 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +192 -0
- package/dist/cli.js.map +1 -0
- package/dist/codegen.d.ts +50 -0
- package/dist/codegen.d.ts.map +1 -0
- package/dist/codegen.js +132 -0
- package/dist/codegen.js.map +1 -0
- package/dist/fetch-tools.d.ts +38 -0
- package/dist/fetch-tools.d.ts.map +1 -0
- package/dist/fetch-tools.js +41 -0
- package/dist/fetch-tools.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/runtime.d.ts +21 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +8 -0
- package/dist/runtime.js.map +1 -0
- package/package.json +53 -0
- package/templates/hooks.tsx.hbs +22 -0
- package/templates/tools.ts.hbs +28 -0
package/README.md
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# @miragon/mcp-toolkit-tool-codegen
|
|
2
|
+
|
|
3
|
+
Build-time codegen + runtime glue for type-safe MCP tool calls: TypedCallTool
|
|
4
|
+
helper and a CLI that generates TypeScript types + React Query hooks from an
|
|
5
|
+
MCP server's tools/list.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
Published to the public npm registry under the `@miragon` scope — no `.npmrc`
|
|
10
|
+
or token needed.
|
|
11
|
+
|
|
12
|
+
```sh
|
|
13
|
+
pnpm add -D @miragon/mcp-toolkit-tool-codegen @miragon/mcp-toolkit-core @modelcontextprotocol/sdk@1.29.0
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Import paths
|
|
17
|
+
|
|
18
|
+
| Subpath | Key exports | Constraint |
|
|
19
|
+
| ----------------------------------- | ---------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
|
|
20
|
+
| `@miragon/mcp-toolkit-tool-codegen` | `generateTools`, `renderCodegen`, `writeCodegenOutput`, `fetchUpstreamTools` | Build-time only — never import from runtime code. |
|
|
21
|
+
| `…-tool-codegen/runtime` | `ToolShape`, `TypedCallTool` (types only) | The only subpath widget bundles / step modules may import; pulls in no `handlebars` / codegen deps. |
|
|
22
|
+
| `…-tool-codegen/templates/*` | Handlebars templates used by the codegen | Internal to the CLI. |
|
|
23
|
+
|
|
24
|
+
## CLI
|
|
25
|
+
|
|
26
|
+
The `mcp-tool-codegen` bin generates `tools.ts` + `hooks.tsx` from a
|
|
27
|
+
source server's `tools/list`:
|
|
28
|
+
|
|
29
|
+
```sh
|
|
30
|
+
mcp-tool-codegen generate # reads ./codegen.config.ts (CodegenConfig)
|
|
31
|
+
mcp-tool-codegen generate --check # CI: exit 1 on drift vs committed output
|
|
32
|
+
mcp-tool-codegen inspect --upstream https://source.example/mcp
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Generated code imports only `@miragon/mcp-toolkit-tool-codegen/runtime`.
|
|
36
|
+
|
|
37
|
+
## Links
|
|
38
|
+
|
|
39
|
+
- [API reference](https://github.com/Miragon/mcp-toolkit/blob/main/docs/reference/api-tool-codegen.md)
|
|
40
|
+
- [Getting started](https://github.com/Miragon/mcp-toolkit/blob/main/docs/getting-started.md)
|
|
41
|
+
- [Starter template](https://github.com/Miragon/mcp-toolkit-starter) — "Use this template" for a new server project
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/* eslint-disable no-console */
|
|
3
|
+
import fs from "node:fs/promises";
|
|
4
|
+
import os from "node:os";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { pathToFileURL } from "node:url";
|
|
7
|
+
import { generateTools, writeCodegenOutput } from "./codegen.js";
|
|
8
|
+
import { fetchUpstreamTools } from "./fetch-tools.js";
|
|
9
|
+
function parseArgs(argv) {
|
|
10
|
+
const args = { command: "help", check: false };
|
|
11
|
+
const [command, ...rest] = argv;
|
|
12
|
+
if (command === "generate" || command === "inspect")
|
|
13
|
+
args.command = command;
|
|
14
|
+
for (let i = 0; i < rest.length; i++) {
|
|
15
|
+
const arg = rest[i];
|
|
16
|
+
const next = () => rest[++i];
|
|
17
|
+
switch (arg) {
|
|
18
|
+
case "--config":
|
|
19
|
+
case "-c":
|
|
20
|
+
args.config = next();
|
|
21
|
+
break;
|
|
22
|
+
case "--check":
|
|
23
|
+
args.check = true;
|
|
24
|
+
break;
|
|
25
|
+
case "--upstream":
|
|
26
|
+
case "-u":
|
|
27
|
+
args.upstream = next();
|
|
28
|
+
break;
|
|
29
|
+
case "--token":
|
|
30
|
+
args.token = next();
|
|
31
|
+
break;
|
|
32
|
+
case "--header":
|
|
33
|
+
args.header = next();
|
|
34
|
+
break;
|
|
35
|
+
case "--header-value":
|
|
36
|
+
args.headerValue = next();
|
|
37
|
+
break;
|
|
38
|
+
case "--out":
|
|
39
|
+
case "-o":
|
|
40
|
+
args.out = next();
|
|
41
|
+
break;
|
|
42
|
+
case "--proxy":
|
|
43
|
+
case "-p":
|
|
44
|
+
args.proxyName = next();
|
|
45
|
+
break;
|
|
46
|
+
case "--help":
|
|
47
|
+
case "-h":
|
|
48
|
+
args.command = "help";
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return args;
|
|
53
|
+
}
|
|
54
|
+
function printHelp() {
|
|
55
|
+
console.log(`mcp-tool-codegen — generate typed TS client code from an MCP server's tools/list.
|
|
56
|
+
|
|
57
|
+
Commands:
|
|
58
|
+
generate [--config <path>] [--check]
|
|
59
|
+
Fetch tools/list and write TypeScript + React Query hooks.
|
|
60
|
+
--check regenerate into a temp dir and exit != 0 if the output differs
|
|
61
|
+
from the committed files (for CI drift checks)
|
|
62
|
+
inspect --upstream <url> [--token <bearer>] [--header <name> --header-value <v>]
|
|
63
|
+
Print a markdown table of the upstream's tools without generating code.
|
|
64
|
+
help
|
|
65
|
+
Show this message.
|
|
66
|
+
|
|
67
|
+
Generate reads its configuration from a file (default: ./codegen.config.ts).
|
|
68
|
+
The config module's default export must satisfy the CodegenConfig type:
|
|
69
|
+
|
|
70
|
+
export default {
|
|
71
|
+
proxyName: "lexoffice",
|
|
72
|
+
upstreamUrl: process.env.LEXOFFICE_CODEGEN_SOURCE_URL,
|
|
73
|
+
auth: { mode: "bearer", token: process.env.LEXOFFICE_CODEGEN_TOKEN },
|
|
74
|
+
out: "./src/generated",
|
|
75
|
+
}
|
|
76
|
+
`);
|
|
77
|
+
}
|
|
78
|
+
async function loadConfig(configPath) {
|
|
79
|
+
const abs = path.resolve(process.cwd(), configPath);
|
|
80
|
+
const mod = (await import(pathToFileURL(abs).href));
|
|
81
|
+
if (!mod.default) {
|
|
82
|
+
throw new Error(`codegen config at ${abs} has no default export`);
|
|
83
|
+
}
|
|
84
|
+
return mod.default;
|
|
85
|
+
}
|
|
86
|
+
async function runGenerate(args) {
|
|
87
|
+
const configPath = args.config ?? "./codegen.config.ts";
|
|
88
|
+
const config = await loadConfig(configPath);
|
|
89
|
+
const result = await generateTools(config);
|
|
90
|
+
if (args.check) {
|
|
91
|
+
const tmp = await fs.mkdtemp(path.join(os.tmpdir(), "mcp-tool-codegen-"));
|
|
92
|
+
try {
|
|
93
|
+
const clone = { ...config, out: tmp };
|
|
94
|
+
await writeCodegenOutput(clone, result);
|
|
95
|
+
await assertMatches(config.out, tmp);
|
|
96
|
+
console.log(`OK (${result.tools.length} tools match committed output)`);
|
|
97
|
+
}
|
|
98
|
+
finally {
|
|
99
|
+
await fs.rm(tmp, { recursive: true, force: true });
|
|
100
|
+
}
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
await writeCodegenOutput(config, result);
|
|
104
|
+
console.log(`generated ${result.tools.length} tools → ${path.resolve(process.cwd(), config.out)}`);
|
|
105
|
+
}
|
|
106
|
+
async function assertMatches(committed, generated) {
|
|
107
|
+
const committedAbs = path.resolve(process.cwd(), committed);
|
|
108
|
+
let drifted = false;
|
|
109
|
+
for (const file of ["tools.ts", "hooks.tsx"]) {
|
|
110
|
+
const a = await fs.readFile(path.join(committedAbs, file), "utf-8").catch(() => null);
|
|
111
|
+
const b = await fs.readFile(path.join(generated, file), "utf-8");
|
|
112
|
+
if (a === null) {
|
|
113
|
+
console.error(`drift: ${file} missing from committed output (${committedAbs})`);
|
|
114
|
+
drifted = true;
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
if (a !== b) {
|
|
118
|
+
console.error(`drift: ${file} differs from committed output`);
|
|
119
|
+
printLineDiff(a, b);
|
|
120
|
+
drifted = true;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
if (drifted)
|
|
124
|
+
process.exit(1);
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Prints the first N differing lines between two strings. Cheap line-level
|
|
128
|
+
* diff (no LCS) — sufficient to tell the user where regeneration would
|
|
129
|
+
* change the file without pulling in a diff library.
|
|
130
|
+
*/
|
|
131
|
+
function printLineDiff(committed, generated, maxLines = 20) {
|
|
132
|
+
const aLines = committed.split("\n");
|
|
133
|
+
const bLines = generated.split("\n");
|
|
134
|
+
const max = Math.max(aLines.length, bLines.length);
|
|
135
|
+
let shown = 0;
|
|
136
|
+
for (let i = 0; i < max && shown < maxLines; i++) {
|
|
137
|
+
const a = aLines[i];
|
|
138
|
+
const b = bLines[i];
|
|
139
|
+
if (a !== b) {
|
|
140
|
+
if (a !== undefined)
|
|
141
|
+
console.error(` - ${i + 1}: ${a}`);
|
|
142
|
+
if (b !== undefined)
|
|
143
|
+
console.error(` + ${i + 1}: ${b}`);
|
|
144
|
+
shown++;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
if (shown >= maxLines) {
|
|
148
|
+
console.error(` ... (truncated; more differences not shown)`);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
async function runInspect(args) {
|
|
152
|
+
if (!args.upstream) {
|
|
153
|
+
console.error("inspect: --upstream <url> is required");
|
|
154
|
+
process.exit(1);
|
|
155
|
+
}
|
|
156
|
+
const auth = resolveAuthFromFlags(args);
|
|
157
|
+
const tools = await fetchUpstreamTools({ upstreamUrl: args.upstream, auth });
|
|
158
|
+
console.log(`| name | description | input keys |`);
|
|
159
|
+
console.log(`| --- | --- | --- |`);
|
|
160
|
+
for (const tool of tools) {
|
|
161
|
+
const inputKeys = Object.keys(tool.inputSchema.properties ?? {});
|
|
162
|
+
const desc = (tool.description ?? "").replace(/\|/g, "\\|").replace(/\n/g, " ");
|
|
163
|
+
console.log(`| ${tool.name} | ${desc} | ${inputKeys.join(", ")} |`);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
function resolveAuthFromFlags(args) {
|
|
167
|
+
if (args.token)
|
|
168
|
+
return { mode: "bearer", token: args.token };
|
|
169
|
+
if (args.header && args.headerValue) {
|
|
170
|
+
return { mode: "header", headerName: args.header, value: args.headerValue };
|
|
171
|
+
}
|
|
172
|
+
return { mode: "none" };
|
|
173
|
+
}
|
|
174
|
+
async function main() {
|
|
175
|
+
const args = parseArgs(process.argv.slice(2));
|
|
176
|
+
try {
|
|
177
|
+
if (args.command === "help") {
|
|
178
|
+
printHelp();
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
if (args.command === "generate")
|
|
182
|
+
return await runGenerate(args);
|
|
183
|
+
if (args.command === "inspect")
|
|
184
|
+
return await runInspect(args);
|
|
185
|
+
}
|
|
186
|
+
catch (err) {
|
|
187
|
+
console.error(err instanceof Error ? err.message : err);
|
|
188
|
+
process.exit(1);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
void main();
|
|
192
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { type FetchToolsOptions, type UpstreamToolDescriptor } from "./fetch-tools.js";
|
|
2
|
+
export interface CodegenConfig {
|
|
3
|
+
/** Namespace prefix for the generated tool names and type names (`<proxyName>_<tool>`). */
|
|
4
|
+
proxyName: string;
|
|
5
|
+
upstreamUrl: string;
|
|
6
|
+
auth?: FetchToolsOptions["auth"];
|
|
7
|
+
/** Output directory (relative paths resolve against process.cwd()). */
|
|
8
|
+
out: string;
|
|
9
|
+
/**
|
|
10
|
+
* Optional per-tool type overrides. Keys are full tool names
|
|
11
|
+
* (`<proxy>_<tool>`), values are literal TypeScript type expressions
|
|
12
|
+
* that replace the codegen output for that tool.
|
|
13
|
+
*
|
|
14
|
+
* Useful when the upstream omits `outputSchema` — generated output type
|
|
15
|
+
* defaults to `unknown`, an override lets you paste a hand-written
|
|
16
|
+
* result shape without editing the generated file.
|
|
17
|
+
*/
|
|
18
|
+
overrides?: Record<string, {
|
|
19
|
+
input?: string;
|
|
20
|
+
output?: string;
|
|
21
|
+
}>;
|
|
22
|
+
}
|
|
23
|
+
export interface CodegenResult {
|
|
24
|
+
toolsFile: string;
|
|
25
|
+
hooksFile: string;
|
|
26
|
+
tools: UpstreamToolDescriptor[];
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Fetches `tools/list` from the upstream MCP, runs `json-schema-to-typescript`
|
|
30
|
+
* on each tool's input/output schemas, and renders the two generated files
|
|
31
|
+
* from the shipped Handlebars templates.
|
|
32
|
+
*
|
|
33
|
+
* Called by the CLI (`mcp-tool-codegen generate`) but exposed programmatically
|
|
34
|
+
* so consumers can wire it into custom build pipelines or tests.
|
|
35
|
+
*/
|
|
36
|
+
export declare function generateTools(config: CodegenConfig): Promise<CodegenResult>;
|
|
37
|
+
/**
|
|
38
|
+
* Renders the two generated files from an explicit list of upstream tools —
|
|
39
|
+
* the pure, network-free half of {@link generateTools}. Split out so the
|
|
40
|
+
* build-time↔runtime naming/output contract can be pinned by a test that feeds
|
|
41
|
+
* a fixed tool list, instead of reaching for a live upstream.
|
|
42
|
+
*
|
|
43
|
+
* Sorts by tool name so two regenerations against the same upstream produce
|
|
44
|
+
* byte-identical output regardless of the upstream's `tools/list` order.
|
|
45
|
+
*/
|
|
46
|
+
export declare function renderCodegen(fetched: UpstreamToolDescriptor[], config: CodegenConfig): Promise<CodegenResult>;
|
|
47
|
+
export declare function toPascalCase(input: string): string;
|
|
48
|
+
/** Resolve an output path against cwd, creating the directory if needed. */
|
|
49
|
+
export declare function writeCodegenOutput(config: CodegenConfig, result: CodegenResult): Promise<void>;
|
|
50
|
+
//# sourceMappingURL=codegen.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codegen.d.ts","sourceRoot":"","sources":["../src/codegen.ts"],"names":[],"mappings":"AAQA,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,sBAAsB,EAC5B,MAAM,kBAAkB,CAAA;AAEzB,MAAM,WAAW,aAAa;IAC5B,2FAA2F;IAC3F,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,CAAC,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAA;IAChC,uEAAuE;IACvE,GAAG,EAAE,MAAM,CAAA;IACX;;;;;;;;OAQG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAChE;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,sBAAsB,EAAE,CAAA;CAChC;AAED;;;;;;;GAOG;AACH,wBAAsB,aAAa,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,CAMjF;AAED;;;;;;;;GAQG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,sBAAsB,EAAE,EACjC,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,aAAa,CAAC,CA2BxB;AAmED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMlD;AAaD,4EAA4E;AAC5E,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,aAAa,EACrB,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,IAAI,CAAC,CAOf"}
|
package/dist/codegen.js
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import Handlebars from "handlebars";
|
|
5
|
+
import { compile as compileJsonSchema, } from "json-schema-to-typescript";
|
|
6
|
+
import { fetchUpstreamTools, } from "./fetch-tools.js";
|
|
7
|
+
/**
|
|
8
|
+
* Fetches `tools/list` from the upstream MCP, runs `json-schema-to-typescript`
|
|
9
|
+
* on each tool's input/output schemas, and renders the two generated files
|
|
10
|
+
* from the shipped Handlebars templates.
|
|
11
|
+
*
|
|
12
|
+
* Called by the CLI (`mcp-tool-codegen generate`) but exposed programmatically
|
|
13
|
+
* so consumers can wire it into custom build pipelines or tests.
|
|
14
|
+
*/
|
|
15
|
+
export async function generateTools(config) {
|
|
16
|
+
const fetched = await fetchUpstreamTools({
|
|
17
|
+
upstreamUrl: config.upstreamUrl,
|
|
18
|
+
auth: config.auth,
|
|
19
|
+
});
|
|
20
|
+
return renderCodegen(fetched, config);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Renders the two generated files from an explicit list of upstream tools —
|
|
24
|
+
* the pure, network-free half of {@link generateTools}. Split out so the
|
|
25
|
+
* build-time↔runtime naming/output contract can be pinned by a test that feeds
|
|
26
|
+
* a fixed tool list, instead of reaching for a live upstream.
|
|
27
|
+
*
|
|
28
|
+
* Sorts by tool name so two regenerations against the same upstream produce
|
|
29
|
+
* byte-identical output regardless of the upstream's `tools/list` order.
|
|
30
|
+
*/
|
|
31
|
+
export async function renderCodegen(fetched, config) {
|
|
32
|
+
const tools = [...fetched].sort((a, b) => a.name.localeCompare(b.name));
|
|
33
|
+
const proxyPascal = toPascalCase(config.proxyName);
|
|
34
|
+
const toolMapName = `${proxyPascal}ToolMap`;
|
|
35
|
+
const toolNameTypeName = `${proxyPascal}ToolName`;
|
|
36
|
+
const callToolTypeName = `${proxyPascal}CallTool`;
|
|
37
|
+
const view = {
|
|
38
|
+
proxyName: config.proxyName,
|
|
39
|
+
upstreamUrl: config.upstreamUrl,
|
|
40
|
+
toolMapName,
|
|
41
|
+
toolNameTypeName,
|
|
42
|
+
callToolTypeName,
|
|
43
|
+
tools: await Promise.all(tools.map((tool) => renderTool(tool, config, proxyPascal))),
|
|
44
|
+
};
|
|
45
|
+
const [toolsTpl, hooksTpl] = await Promise.all([
|
|
46
|
+
loadTemplate("tools.ts.hbs"),
|
|
47
|
+
loadTemplate("hooks.tsx.hbs"),
|
|
48
|
+
]);
|
|
49
|
+
return {
|
|
50
|
+
toolsFile: normalizeEof(toolsTpl(view)),
|
|
51
|
+
hooksFile: normalizeEof(hooksTpl(view)),
|
|
52
|
+
tools,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Exactly one trailing newline, so committed output passes the repo's
|
|
57
|
+
* Prettier gate while staying byte-identical to `generate --check`.
|
|
58
|
+
*/
|
|
59
|
+
function normalizeEof(rendered) {
|
|
60
|
+
return rendered.replace(/\n*$/, "\n");
|
|
61
|
+
}
|
|
62
|
+
async function renderTool(tool, config, proxyPascal) {
|
|
63
|
+
const toolPascal = toPascalCase(tool.name);
|
|
64
|
+
const inputTypeName = `${proxyPascal}${toolPascal}Input`;
|
|
65
|
+
const outputTypeName = `${proxyPascal}${toolPascal}Output`;
|
|
66
|
+
const fullName = `${config.proxyName}_${tool.name}`;
|
|
67
|
+
const override = config.overrides?.[fullName];
|
|
68
|
+
const inputTypeBody = override?.input
|
|
69
|
+
? undefined
|
|
70
|
+
: await schemaToType(tool.inputSchema, inputTypeName);
|
|
71
|
+
const outputTypeBody = override?.output
|
|
72
|
+
? undefined
|
|
73
|
+
: tool.outputSchema
|
|
74
|
+
? await schemaToType(tool.outputSchema, outputTypeName)
|
|
75
|
+
: undefined;
|
|
76
|
+
const inputTypeRef = override?.input ?? (inputTypeBody ? inputTypeName : "unknown");
|
|
77
|
+
const outputTypeRef = override?.output ?? (outputTypeBody ? outputTypeName : "unknown");
|
|
78
|
+
return {
|
|
79
|
+
name: tool.name,
|
|
80
|
+
fullName,
|
|
81
|
+
quotedFullName: JSON.stringify(fullName),
|
|
82
|
+
hookName: `use${proxyPascal}${toolPascal}`,
|
|
83
|
+
inputTypeBody,
|
|
84
|
+
outputTypeBody,
|
|
85
|
+
inputTypeRef,
|
|
86
|
+
outputTypeRef,
|
|
87
|
+
// Prettier-style spacing so committed output passes the repo's format gate
|
|
88
|
+
// without breaking `generate --check`'s byte comparison.
|
|
89
|
+
queryKey: `[${JSON.stringify(config.proxyName)}, ${JSON.stringify(tool.name)}]`,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
const json2tsOptions = {
|
|
93
|
+
bannerComment: "",
|
|
94
|
+
additionalProperties: false,
|
|
95
|
+
style: { singleQuote: false, semi: false },
|
|
96
|
+
unreachableDefinitions: false,
|
|
97
|
+
};
|
|
98
|
+
async function schemaToType(schema, name) {
|
|
99
|
+
const result = await compileJsonSchema(
|
|
100
|
+
// json-schema-to-typescript treats the top-level title as the type name,
|
|
101
|
+
// and `title` beats the `name` arg to `compile()`. Spread first so an
|
|
102
|
+
// upstream-supplied title can't override the codegen's chosen name.
|
|
103
|
+
{ ...schema, title: name }, name, json2tsOptions);
|
|
104
|
+
return result.trim();
|
|
105
|
+
}
|
|
106
|
+
export function toPascalCase(input) {
|
|
107
|
+
return input
|
|
108
|
+
.split(/[-_\s]+/)
|
|
109
|
+
.filter(Boolean)
|
|
110
|
+
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
|
111
|
+
.join("");
|
|
112
|
+
}
|
|
113
|
+
let templateDir;
|
|
114
|
+
async function loadTemplate(name) {
|
|
115
|
+
if (!templateDir) {
|
|
116
|
+
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
117
|
+
// dist/codegen.js → ../templates
|
|
118
|
+
templateDir = path.resolve(here, "..", "templates");
|
|
119
|
+
}
|
|
120
|
+
const src = await fs.readFile(path.join(templateDir, name), "utf-8");
|
|
121
|
+
return Handlebars.compile(src, { noEscape: true });
|
|
122
|
+
}
|
|
123
|
+
/** Resolve an output path against cwd, creating the directory if needed. */
|
|
124
|
+
export async function writeCodegenOutput(config, result) {
|
|
125
|
+
const outDir = path.resolve(process.cwd(), config.out);
|
|
126
|
+
await fs.mkdir(outDir, { recursive: true });
|
|
127
|
+
await Promise.all([
|
|
128
|
+
fs.writeFile(path.join(outDir, "tools.ts"), result.toolsFile),
|
|
129
|
+
fs.writeFile(path.join(outDir, "hooks.tsx"), result.hooksFile),
|
|
130
|
+
]);
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=codegen.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codegen.js","sourceRoot":"","sources":["../src/codegen.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export interface UpstreamToolDescriptor {
|
|
2
|
+
name: string;
|
|
3
|
+
description?: string;
|
|
4
|
+
title?: string;
|
|
5
|
+
inputSchema: Record<string, unknown>;
|
|
6
|
+
outputSchema?: Record<string, unknown>;
|
|
7
|
+
}
|
|
8
|
+
export interface FetchToolsOptions {
|
|
9
|
+
upstreamUrl: string;
|
|
10
|
+
/**
|
|
11
|
+
* Static auth for the build-time handshake. OAuth2 is not supported here —
|
|
12
|
+
* run the OAuth2 flow once in dev, paste the resulting access token, and
|
|
13
|
+
* use `{ mode: "bearer", token }` for subsequent regenerations.
|
|
14
|
+
*/
|
|
15
|
+
auth?: {
|
|
16
|
+
mode: "none";
|
|
17
|
+
} | {
|
|
18
|
+
mode: "bearer";
|
|
19
|
+
token: string;
|
|
20
|
+
} | {
|
|
21
|
+
mode: "header";
|
|
22
|
+
headerName: string;
|
|
23
|
+
value: string;
|
|
24
|
+
};
|
|
25
|
+
/** Optional request headers to merge on top of the auth header. */
|
|
26
|
+
headers?: Record<string, string>;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Connects to an upstream MCP server over streamable HTTP, performs the
|
|
30
|
+
* initialize handshake, and returns the `tools/list` response. The
|
|
31
|
+
* connection is closed before returning.
|
|
32
|
+
*
|
|
33
|
+
* Used by the codegen CLI (`generate` / `inspect`) to snapshot a source
|
|
34
|
+
* server's tool surface. Build-time only — not intended for request-path
|
|
35
|
+
* use at runtime.
|
|
36
|
+
*/
|
|
37
|
+
export declare function fetchUpstreamTools(options: FetchToolsOptions): Promise<UpstreamToolDescriptor[]>;
|
|
38
|
+
//# sourceMappingURL=fetch-tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch-tools.d.ts","sourceRoot":"","sources":["../src/fetch-tools.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACpC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACvC;AAED,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,CAAA;IACnB;;;;OAIG;IACH,IAAI,CAAC,EACD;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,GAChB;QAAE,IAAI,EAAE,QAAQ,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GACjC;QAAE,IAAI,EAAE,QAAQ,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;IACzD,mEAAmE;IACnE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACjC;AAQD;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,sBAAsB,EAAE,CAAC,CAqBnC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
2
|
+
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
3
|
+
function authHeaders(auth) {
|
|
4
|
+
if (!auth || auth.mode === "none")
|
|
5
|
+
return {};
|
|
6
|
+
if (auth.mode === "bearer")
|
|
7
|
+
return { authorization: `Bearer ${auth.token}` };
|
|
8
|
+
return { [auth.headerName.toLowerCase()]: auth.value };
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Connects to an upstream MCP server over streamable HTTP, performs the
|
|
12
|
+
* initialize handshake, and returns the `tools/list` response. The
|
|
13
|
+
* connection is closed before returning.
|
|
14
|
+
*
|
|
15
|
+
* Used by the codegen CLI (`generate` / `inspect`) to snapshot a source
|
|
16
|
+
* server's tool surface. Build-time only — not intended for request-path
|
|
17
|
+
* use at runtime.
|
|
18
|
+
*/
|
|
19
|
+
export async function fetchUpstreamTools(options) {
|
|
20
|
+
const url = new URL(options.upstreamUrl);
|
|
21
|
+
const requestInit = {
|
|
22
|
+
headers: { ...authHeaders(options.auth), ...(options.headers ?? {}) },
|
|
23
|
+
};
|
|
24
|
+
const transport = new StreamableHTTPClientTransport(url, { requestInit });
|
|
25
|
+
const client = new Client({ name: "mcp-tool-codegen", version: "0.1.0" }, { capabilities: {} });
|
|
26
|
+
try {
|
|
27
|
+
await client.connect(transport);
|
|
28
|
+
const result = await client.listTools();
|
|
29
|
+
return result.tools.map((t) => ({
|
|
30
|
+
name: t.name,
|
|
31
|
+
description: t.description,
|
|
32
|
+
title: t.title,
|
|
33
|
+
inputSchema: t.inputSchema,
|
|
34
|
+
outputSchema: t.outputSchema,
|
|
35
|
+
}));
|
|
36
|
+
}
|
|
37
|
+
finally {
|
|
38
|
+
await client.close().catch(() => { });
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=fetch-tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch-tools.js","sourceRoot":"","sources":["../src/fetch-tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAA;AAClE,OAAO,EAAE,6BAA6B,EAAE,MAAM,oDAAoD,CAAA;AAyBlG,SAAS,WAAW,CAAC,IAA+B;IAClD,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM;QAAE,OAAO,EAAE,CAAA;IAC5C,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ;QAAE,OAAO,EAAE,aAAa,EAAE,UAAU,IAAI,CAAC,KAAK,EAAE,EAAE,CAAA;IAC5E,OAAO,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,EAAE,IAAI,CAAC,KAAK,EAAE,CAAA;AACxD,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,OAA0B;IAE1B,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,CAAA;IACxC,MAAM,WAAW,GAAgB;QAC/B,OAAO,EAAE,EAAE,GAAG,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC,EAAE;KACtE,CAAA;IACD,MAAM,SAAS,GAAG,IAAI,6BAA6B,CAAC,GAAG,EAAE,EAAE,WAAW,EAAE,CAAC,CAAA;IACzE,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,EAAE,IAAI,EAAE,kBAAkB,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC,CAAA;IAE/F,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;QAC/B,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,SAAS,EAAE,CAAA;QACvC,OAAO,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC9B,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,WAAW,EAAE,CAAC,CAAC,WAAW;YAC1B,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,WAAW,EAAE,CAAC,CAAC,WAAW;YAC1B,YAAY,EAAE,CAAC,CAAC,YAAY;SAC7B,CAAC,CAAC,CAAA;IACL,CAAC;YAAS,CAAC;QACT,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;IACtC,CAAC;AACH,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export type { ToolShape, TypedCallTool } from "./runtime.js";
|
|
2
|
+
export { fetchUpstreamTools } from "./fetch-tools.js";
|
|
3
|
+
export type { FetchToolsOptions, UpstreamToolDescriptor } from "./fetch-tools.js";
|
|
4
|
+
export { generateTools, renderCodegen, writeCodegenOutput } from "./codegen.js";
|
|
5
|
+
export type { CodegenConfig, CodegenResult } from "./codegen.js";
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AACrD,YAAY,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAA;AACjF,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAA;AAC/E,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AAErD,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAA"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime types referenced by codegen output. Kept in their own subpath
|
|
3
|
+
* (`@miragon/mcp-toolkit-tool-codegen/runtime`) so widget bundles and
|
|
4
|
+
* step modules can import the types without pulling in the CLI / codegen
|
|
5
|
+
* dependencies (handlebars, json-schema-to-typescript).
|
|
6
|
+
*/
|
|
7
|
+
export interface ToolShape {
|
|
8
|
+
input: unknown;
|
|
9
|
+
output: unknown;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* A typed `callTool` closure bound to a specific upstream-MCP's tool map.
|
|
13
|
+
* The `TMap` type is filled in by the generated `<Proxy>ToolMap` interface;
|
|
14
|
+
* consumers write `TypedCallTool<LexofficeToolMap>` and get auto-completion
|
|
15
|
+
* plus compile-time validation on tool names, args, and results.
|
|
16
|
+
*
|
|
17
|
+
* Surface is deliberately 2-arg — the framework pipeline executor injects
|
|
18
|
+
* the caller's userId behind the scenes so step code stays clean.
|
|
19
|
+
*/
|
|
20
|
+
export type TypedCallTool<TMap extends Record<string, ToolShape>> = <TName extends keyof TMap & string>(name: TName, args: TMap[TName]["input"]) => Promise<TMap[TName]["output"]>;
|
|
21
|
+
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,OAAO,CAAA;IACd,MAAM,EAAE,OAAO,CAAA;CAChB;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,aAAa,CAAC,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,IAAI,CAClE,KAAK,SAAS,MAAM,IAAI,GAAG,MAAM,EAEjC,IAAI,EAAE,KAAK,EACX,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,KACvB,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAA"}
|
package/dist/runtime.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime types referenced by codegen output. Kept in their own subpath
|
|
3
|
+
* (`@miragon/mcp-toolkit-tool-codegen/runtime`) so widget bundles and
|
|
4
|
+
* step modules can import the types without pulling in the CLI / codegen
|
|
5
|
+
* dependencies (handlebars, json-schema-to-typescript).
|
|
6
|
+
*/
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@miragon/mcp-toolkit-tool-codegen",
|
|
3
|
+
"version": "0.10.1",
|
|
4
|
+
"description": "Build-time codegen + runtime glue for type-safe MCP tool calls: TypedCallTool helper and a CLI that generates TypeScript types + React Query hooks from an MCP server's tools/list.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"sideEffects": false,
|
|
7
|
+
"main": "dist/index.js",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"bin": {
|
|
10
|
+
"mcp-tool-codegen": "dist/cli.js"
|
|
11
|
+
},
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"import": "./dist/index.js"
|
|
16
|
+
},
|
|
17
|
+
"./runtime": {
|
|
18
|
+
"types": "./dist/runtime.d.ts",
|
|
19
|
+
"import": "./dist/runtime.js"
|
|
20
|
+
},
|
|
21
|
+
"./templates/*": "./templates/*"
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
"dist",
|
|
25
|
+
"templates",
|
|
26
|
+
"README.md"
|
|
27
|
+
],
|
|
28
|
+
"publishConfig": {
|
|
29
|
+
"access": "public"
|
|
30
|
+
},
|
|
31
|
+
"peerDependencies": {
|
|
32
|
+
"@modelcontextprotocol/sdk": "1.29.0",
|
|
33
|
+
"@miragon/mcp-toolkit-core": "0.10.1"
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"handlebars": "4.7.9",
|
|
37
|
+
"json-schema-to-typescript": "15.0.4"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@modelcontextprotocol/sdk": "1.29.0",
|
|
41
|
+
"@types/node": "26.1.1",
|
|
42
|
+
"typescript": "6.0.3",
|
|
43
|
+
"vitest": "4.1.10",
|
|
44
|
+
"@miragon/mcp-toolkit-core": "0.10.1"
|
|
45
|
+
},
|
|
46
|
+
"scripts": {
|
|
47
|
+
"build": "tsc -p tsconfig.build.json && node scripts/make-cli-executable.mjs",
|
|
48
|
+
"typecheck": "tsc --noEmit",
|
|
49
|
+
"test": "vitest run",
|
|
50
|
+
"lint": "eslint src --max-warnings 0",
|
|
51
|
+
"lint:fix": "eslint src --fix"
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// AUTO-GENERATED by @miragon/mcp-toolkit-tool-codegen. Do not edit by hand.
|
|
2
|
+
// Regenerate with: pnpm mcp-tool-codegen generate
|
|
3
|
+
// Source: {{upstreamUrl}}
|
|
4
|
+
// Proxy: {{proxyName}}
|
|
5
|
+
|
|
6
|
+
import { useToolQuery, type UseToolQueryOptions } from "@miragon/mcp-toolkit-ui"
|
|
7
|
+
import type { {{toolMapName}} } from "./tools.js"
|
|
8
|
+
|
|
9
|
+
{{#each tools}}
|
|
10
|
+
export function {{hookName}}(
|
|
11
|
+
args: {{../toolMapName}}[{{{quotedFullName}}}]["input"],
|
|
12
|
+
options?: UseToolQueryOptions<{{../toolMapName}}[{{{quotedFullName}}}]["output"]>,
|
|
13
|
+
) {
|
|
14
|
+
return useToolQuery<{{../toolMapName}}[{{{quotedFullName}}}]["output"]>(
|
|
15
|
+
{{{queryKey}}},
|
|
16
|
+
{{{quotedFullName}}},
|
|
17
|
+
args,
|
|
18
|
+
options,
|
|
19
|
+
)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
{{/each}}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// AUTO-GENERATED by @miragon/mcp-toolkit-tool-codegen. Do not edit by hand.
|
|
2
|
+
// Regenerate with: pnpm mcp-tool-codegen generate
|
|
3
|
+
// Source: {{upstreamUrl}}
|
|
4
|
+
// Proxy: {{proxyName}}
|
|
5
|
+
/* eslint-disable @typescript-eslint/no-empty-object-type */
|
|
6
|
+
|
|
7
|
+
import type { ToolShape, TypedCallTool } from "@miragon/mcp-toolkit-tool-codegen/runtime"
|
|
8
|
+
|
|
9
|
+
{{#each tools}}
|
|
10
|
+
{{#if inputTypeBody}}
|
|
11
|
+
{{{inputTypeBody}}}
|
|
12
|
+
{{/if}}
|
|
13
|
+
{{#if outputTypeBody}}
|
|
14
|
+
{{{outputTypeBody}}}
|
|
15
|
+
{{/if}}
|
|
16
|
+
{{/each}}
|
|
17
|
+
|
|
18
|
+
export interface {{toolMapName}} extends Record<string, ToolShape> {
|
|
19
|
+
{{#each tools}}
|
|
20
|
+
{{{quotedFullName}}}: {
|
|
21
|
+
input: {{inputTypeRef}}
|
|
22
|
+
output: {{outputTypeRef}}
|
|
23
|
+
}
|
|
24
|
+
{{/each}}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export type {{toolNameTypeName}} = keyof {{toolMapName}} & string
|
|
28
|
+
export type {{callToolTypeName}} = TypedCallTool<{{toolMapName}}>
|