opentool 0.6.4 → 0.7.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.
- package/README.md +31 -0
- package/dist/cli/index.d.ts +13 -3
- package/dist/cli/index.js +176 -10
- package/dist/cli/index.js.map +1 -1
- package/dist/index-D_bCF2Bf.d.ts +487 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +11 -11
- package/dist/index.js.map +1 -1
- package/dist/payment/index.d.ts +1 -1
- package/dist/payment/index.js +2 -2
- package/dist/payment/index.js.map +1 -1
- package/dist/validate-CqB2Juma.d.ts +216 -0
- package/package.json +6 -4
- package/dist/index-D3DaM5Rs.d.ts +0 -1693
- package/dist/validate-BLlooEBK.d.ts +0 -842
package/README.md
CHANGED
|
@@ -113,6 +113,37 @@ npx mcp-inspector --config inspector.json --server opentool-dev
|
|
|
113
113
|
|
|
114
114
|
Copy `.env.example` to `.env` and add your credentials if you're using wallet/payment features. The inspector starts `opentool dev` automatically, so you only need one terminal. Only tools with `mcp = { enabled: true }` show up in the inspector - HTTP-only tools keep running on localhost.
|
|
115
115
|
|
|
116
|
+
### Quick x402 test with curl
|
|
117
|
+
|
|
118
|
+
1. Start the dev server against the example tools:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
npx opentool dev --input examples/full-metadata/tools
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
2. Trigger the paywall and inspect the returned payment requirements:
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
curl -i \
|
|
128
|
+
-X POST http://localhost:7000/premium-report \
|
|
129
|
+
-H "content-type: application/json" \
|
|
130
|
+
-d '{"symbol":"BTC"}'
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
The response includes a `402 Payment Required` status and JSON body with an `x402.accepts[0]` object describing the payment request.
|
|
134
|
+
|
|
135
|
+
3. Submit a follow-up request with an `X-PAYMENT` header produced by your x402 facilitator (for example, by using the Coinbase [x402](https://github.com/coinbase/x402) tooling or your own signing flow):
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
curl -i \
|
|
139
|
+
-X POST http://localhost:7000/premium-report \
|
|
140
|
+
-H "content-type: application/json" \
|
|
141
|
+
-H "X-PAYMENT: ${X402_HEADER}" \
|
|
142
|
+
-d '{"symbol":"BTC"}'
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Replace `${X402_HEADER}` with the base64-encoded payment payload returned by your facilitator’s `/verify` or `/pay` workflow. If the payment is valid the server responds with `200 OK`; otherwise it returns a new `402` with failure details.
|
|
146
|
+
|
|
116
147
|
### 5. Build for deployment
|
|
117
148
|
|
|
118
149
|
```bash
|
package/dist/cli/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { h as Metadata, I as InternalToolDefinition } from '../validate-
|
|
3
|
-
export { G as GenerateMetadataOptions, i as GenerateMetadataResult, V as ValidateOptions, g as generateMetadata, a as generateMetadataCommand, l as loadAndValidateTools, v as validateCommand, j as validateFullCommand } from '../validate-
|
|
2
|
+
import { h as Metadata, I as InternalToolDefinition } from '../validate-CqB2Juma.js';
|
|
3
|
+
export { G as GenerateMetadataOptions, i as GenerateMetadataResult, V as ValidateOptions, g as generateMetadata, a as generateMetadataCommand, l as loadAndValidateTools, v as validateCommand, j as validateFullCommand } from '../validate-CqB2Juma.js';
|
|
4
4
|
import 'zod';
|
|
5
|
-
import '../index-
|
|
5
|
+
import '../index-D_bCF2Bf.js';
|
|
6
6
|
|
|
7
7
|
interface BuildOptions {
|
|
8
8
|
input: string;
|
|
@@ -15,6 +15,7 @@ interface BuildArtifacts {
|
|
|
15
15
|
defaultsApplied: string[];
|
|
16
16
|
tools: InternalToolDefinition[];
|
|
17
17
|
compiledTools: CompiledToolArtifact[];
|
|
18
|
+
workflowBundles: WorkflowBundleArtifact | null;
|
|
18
19
|
}
|
|
19
20
|
interface CompiledToolArtifact {
|
|
20
21
|
name: string;
|
|
@@ -25,6 +26,15 @@ interface CompiledToolArtifact {
|
|
|
25
26
|
defaultMcpMethod?: string;
|
|
26
27
|
hasWallet: boolean;
|
|
27
28
|
}
|
|
29
|
+
interface WorkflowBundleArtifact {
|
|
30
|
+
sourceDir: string;
|
|
31
|
+
outputDir: string;
|
|
32
|
+
stepsBundlePath: string;
|
|
33
|
+
workflowsBundlePath: string;
|
|
34
|
+
webhookBundlePath: string;
|
|
35
|
+
clientBundlePath?: string;
|
|
36
|
+
manifestPath?: string;
|
|
37
|
+
}
|
|
28
38
|
declare function buildCommand(options: BuildOptions): Promise<void>;
|
|
29
39
|
declare function buildProject(options: BuildOptions): Promise<BuildArtifacts>;
|
|
30
40
|
|
package/dist/cli/index.js
CHANGED
|
@@ -7,7 +7,7 @@ import { build } from 'esbuild';
|
|
|
7
7
|
import { z } from 'zod';
|
|
8
8
|
import { createRequire } from 'module';
|
|
9
9
|
import { fileURLToPath, pathToFileURL } from 'url';
|
|
10
|
-
import { zodToJsonSchema } from 'zod-to-json-schema';
|
|
10
|
+
import { zodToJsonSchema } from '@alcyone-labs/zod-to-json-schema';
|
|
11
11
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
12
12
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
13
13
|
import { ListToolsRequestSchema, CallToolRequestSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
@@ -95,7 +95,7 @@ var PaymentConfigSchema = z.object({
|
|
|
95
95
|
plain402: z.boolean().optional(),
|
|
96
96
|
acceptedMethods: z.array(z.union([z.literal("x402"), z.literal("402")])).optional(),
|
|
97
97
|
acceptedCurrencies: z.array(z.string()).optional(),
|
|
98
|
-
|
|
98
|
+
chains: z.array(z.union([z.string(), z.number()])).optional(),
|
|
99
99
|
facilitator: z.string().optional()
|
|
100
100
|
}).strict();
|
|
101
101
|
var DiscoveryMetadataSchema = z.object({
|
|
@@ -103,9 +103,9 @@ var DiscoveryMetadataSchema = z.object({
|
|
|
103
103
|
category: z.string().optional(),
|
|
104
104
|
useCases: z.array(z.string()).optional(),
|
|
105
105
|
capabilities: z.array(z.string()).optional(),
|
|
106
|
-
requirements: z.record(z.any()).optional(),
|
|
107
|
-
pricing: z.record(z.any()).optional(),
|
|
108
|
-
compatibility: z.record(z.any()).optional(),
|
|
106
|
+
requirements: z.record(z.string(), z.any()).optional(),
|
|
107
|
+
pricing: z.record(z.string(), z.any()).optional(),
|
|
108
|
+
compatibility: z.record(z.string(), z.any()).optional(),
|
|
109
109
|
documentation: z.union([z.string(), z.array(z.string())]).optional()
|
|
110
110
|
}).catchall(z.any());
|
|
111
111
|
var ToolMetadataOverridesSchema = z.object({
|
|
@@ -148,9 +148,9 @@ var AuthoredMetadataSchema = z.object({
|
|
|
148
148
|
keywords: z.array(z.string()).optional(),
|
|
149
149
|
useCases: z.array(z.string()).optional(),
|
|
150
150
|
capabilities: z.array(z.string()).optional(),
|
|
151
|
-
requirements: z.record(z.any()).optional(),
|
|
152
|
-
pricing: z.record(z.any()).optional(),
|
|
153
|
-
compatibility: z.record(z.any()).optional(),
|
|
151
|
+
requirements: z.record(z.string(), z.any()).optional(),
|
|
152
|
+
pricing: z.record(z.string(), z.any()).optional(),
|
|
153
|
+
compatibility: z.record(z.string(), z.any()).optional(),
|
|
154
154
|
chains: z.array(z.union([z.string(), z.number()])).optional()
|
|
155
155
|
}).catchall(z.any());
|
|
156
156
|
var MetadataSchema = z.object({
|
|
@@ -409,7 +409,7 @@ function resolvePayment(authored, defaults) {
|
|
|
409
409
|
plain402: acceptedMethods.includes("402"),
|
|
410
410
|
acceptedMethods,
|
|
411
411
|
acceptedCurrencies: Array.isArray(pricing.acceptedCurrencies) ? pricing.acceptedCurrencies : ["USDC"],
|
|
412
|
-
|
|
412
|
+
chains: Array.isArray(pricing.chains) ? pricing.chains : [8453]
|
|
413
413
|
};
|
|
414
414
|
}
|
|
415
415
|
function buildDiscovery(authored) {
|
|
@@ -1667,6 +1667,10 @@ async function buildProject(options) {
|
|
|
1667
1667
|
projectRoot,
|
|
1668
1668
|
outputDir
|
|
1669
1669
|
});
|
|
1670
|
+
const workflowBundles = await buildWorkflowsIfPresent({
|
|
1671
|
+
projectRoot,
|
|
1672
|
+
outputDir
|
|
1673
|
+
});
|
|
1670
1674
|
const shouldBuildMcpServer = compiledTools.some((artifact) => artifact.mcpEnabled);
|
|
1671
1675
|
if (shouldBuildMcpServer) {
|
|
1672
1676
|
await writeMcpServer({
|
|
@@ -1684,7 +1688,8 @@ async function buildProject(options) {
|
|
|
1684
1688
|
metadata,
|
|
1685
1689
|
defaultsApplied,
|
|
1686
1690
|
tools,
|
|
1687
|
-
compiledTools
|
|
1691
|
+
compiledTools,
|
|
1692
|
+
workflowBundles
|
|
1688
1693
|
};
|
|
1689
1694
|
}
|
|
1690
1695
|
async function emitTools(tools, config) {
|
|
@@ -1843,6 +1848,18 @@ function logBuildSummary(artifacts, options) {
|
|
|
1843
1848
|
console.log(` - ${tool.name} [${methods}]${walletBadge}`);
|
|
1844
1849
|
});
|
|
1845
1850
|
console.log(" \u2022 metadata.json (registry artifact)");
|
|
1851
|
+
if (artifacts.workflowBundles) {
|
|
1852
|
+
console.log(" \u2022 .well-known/workflow/v1/ (workflow bundles)");
|
|
1853
|
+
console.log(" - flow.js");
|
|
1854
|
+
console.log(" - step.js");
|
|
1855
|
+
console.log(" - webhook.js");
|
|
1856
|
+
if (artifacts.workflowBundles.clientBundlePath) {
|
|
1857
|
+
console.log(" - client.js");
|
|
1858
|
+
}
|
|
1859
|
+
if (artifacts.workflowBundles.manifestPath) {
|
|
1860
|
+
console.log(" - manifest.json");
|
|
1861
|
+
}
|
|
1862
|
+
}
|
|
1846
1863
|
if (artifacts.defaultsApplied.length > 0) {
|
|
1847
1864
|
console.log("\nDefaults applied during metadata synthesis:");
|
|
1848
1865
|
artifacts.defaultsApplied.forEach((entry) => console.log(` \u2022 ${entry}`));
|
|
@@ -1851,6 +1868,155 @@ function logBuildSummary(artifacts, options) {
|
|
|
1851
1868
|
console.log("\n\u2139\uFE0F MCP adapter skipped (no tools opted in)");
|
|
1852
1869
|
}
|
|
1853
1870
|
}
|
|
1871
|
+
async function buildWorkflowsIfPresent(options) {
|
|
1872
|
+
const workflowsDir = options.workflowsDir ?? path5.join(options.projectRoot, "workflows");
|
|
1873
|
+
if (!fs4.existsSync(workflowsDir)) {
|
|
1874
|
+
return null;
|
|
1875
|
+
}
|
|
1876
|
+
if (!hasWorkflowSourceFiles(workflowsDir)) {
|
|
1877
|
+
return null;
|
|
1878
|
+
}
|
|
1879
|
+
const nodeVersion = process.versions?.node ?? "0.0.0";
|
|
1880
|
+
const nodeMajor = Number(nodeVersion.split(".")[0] ?? 0);
|
|
1881
|
+
if (!Number.isFinite(nodeMajor) || nodeMajor < 22) {
|
|
1882
|
+
console.warn(
|
|
1883
|
+
`[${timestamp()}] Workflow bundles skipped (requires Node >= 22, current ${nodeVersion})`
|
|
1884
|
+
);
|
|
1885
|
+
return null;
|
|
1886
|
+
}
|
|
1887
|
+
const { BaseBuilder } = await import('@workflow/cli/dist/lib/builders/base-builder.js');
|
|
1888
|
+
class OpenToolWorkflowBuilder extends BaseBuilder {
|
|
1889
|
+
async build() {
|
|
1890
|
+
const inputFiles = await this.getInputFiles();
|
|
1891
|
+
const tsConfig = await this.getTsConfigOptions();
|
|
1892
|
+
const shared = {
|
|
1893
|
+
inputFiles,
|
|
1894
|
+
...tsConfig.baseUrl ? { tsBaseUrl: tsConfig.baseUrl } : {},
|
|
1895
|
+
...tsConfig.paths ? { tsPaths: tsConfig.paths } : {}
|
|
1896
|
+
};
|
|
1897
|
+
await this.buildStepsBundle(shared);
|
|
1898
|
+
await this.buildWorkflowsBundle(shared);
|
|
1899
|
+
await this.buildWebhookRoute();
|
|
1900
|
+
await this.buildClientLibrary();
|
|
1901
|
+
}
|
|
1902
|
+
async buildStepsBundle(options2) {
|
|
1903
|
+
console.log(
|
|
1904
|
+
"Creating OpenTool workflow steps bundle at",
|
|
1905
|
+
this.config.stepsBundlePath
|
|
1906
|
+
);
|
|
1907
|
+
const stepsBundlePath2 = path5.resolve(
|
|
1908
|
+
this.config.workingDir,
|
|
1909
|
+
this.config.stepsBundlePath
|
|
1910
|
+
);
|
|
1911
|
+
await fs4.promises.mkdir(path5.dirname(stepsBundlePath2), { recursive: true });
|
|
1912
|
+
await this.createStepsBundle({
|
|
1913
|
+
outfile: stepsBundlePath2,
|
|
1914
|
+
...options2
|
|
1915
|
+
});
|
|
1916
|
+
}
|
|
1917
|
+
async buildWorkflowsBundle(options2) {
|
|
1918
|
+
console.log(
|
|
1919
|
+
"Creating OpenTool workflow bundle at",
|
|
1920
|
+
this.config.workflowsBundlePath
|
|
1921
|
+
);
|
|
1922
|
+
const workflowBundlePath = path5.resolve(
|
|
1923
|
+
this.config.workingDir,
|
|
1924
|
+
this.config.workflowsBundlePath
|
|
1925
|
+
);
|
|
1926
|
+
await fs4.promises.mkdir(path5.dirname(workflowBundlePath), {
|
|
1927
|
+
recursive: true
|
|
1928
|
+
});
|
|
1929
|
+
await this.createWorkflowsBundle({
|
|
1930
|
+
outfile: workflowBundlePath,
|
|
1931
|
+
bundleFinalOutput: false,
|
|
1932
|
+
...options2
|
|
1933
|
+
});
|
|
1934
|
+
}
|
|
1935
|
+
async buildWebhookRoute() {
|
|
1936
|
+
console.log(
|
|
1937
|
+
"Creating OpenTool workflow webhook bundle at",
|
|
1938
|
+
this.config.webhookBundlePath
|
|
1939
|
+
);
|
|
1940
|
+
const webhookBundlePath2 = path5.resolve(
|
|
1941
|
+
this.config.workingDir,
|
|
1942
|
+
this.config.webhookBundlePath
|
|
1943
|
+
);
|
|
1944
|
+
await fs4.promises.mkdir(path5.dirname(webhookBundlePath2), {
|
|
1945
|
+
recursive: true
|
|
1946
|
+
});
|
|
1947
|
+
await this.createWebhookBundle({ outfile: webhookBundlePath2 });
|
|
1948
|
+
}
|
|
1949
|
+
}
|
|
1950
|
+
const relativeSourceDir = path5.relative(options.projectRoot, workflowsDir) || ".";
|
|
1951
|
+
const outputBase = path5.join(
|
|
1952
|
+
options.outputDir,
|
|
1953
|
+
".well-known",
|
|
1954
|
+
"workflow",
|
|
1955
|
+
"v1"
|
|
1956
|
+
);
|
|
1957
|
+
const stepsBundlePath = path5.join(outputBase, "step.js");
|
|
1958
|
+
const workflowsBundlePath = path5.join(outputBase, "flow.js");
|
|
1959
|
+
const webhookBundlePath = path5.join(outputBase, "webhook.js");
|
|
1960
|
+
const manifestPath = path5.join(outputBase, "manifest.json");
|
|
1961
|
+
const builder = new OpenToolWorkflowBuilder({
|
|
1962
|
+
workingDir: options.projectRoot,
|
|
1963
|
+
dirs: [relativeSourceDir],
|
|
1964
|
+
buildTarget: "standalone",
|
|
1965
|
+
stepsBundlePath,
|
|
1966
|
+
workflowsBundlePath,
|
|
1967
|
+
webhookBundlePath,
|
|
1968
|
+
...{},
|
|
1969
|
+
workflowManifestPath: manifestPath,
|
|
1970
|
+
externalPackages: [
|
|
1971
|
+
"workflow",
|
|
1972
|
+
"workflow/internal/builtins",
|
|
1973
|
+
"workflow/internal/private",
|
|
1974
|
+
"workflow/runtime",
|
|
1975
|
+
"workflow/api"
|
|
1976
|
+
]
|
|
1977
|
+
});
|
|
1978
|
+
console.log(
|
|
1979
|
+
`[${timestamp()}] Building workflows from ${workflowsDir} -> ${outputBase}`
|
|
1980
|
+
);
|
|
1981
|
+
await builder.build();
|
|
1982
|
+
return {
|
|
1983
|
+
sourceDir: workflowsDir,
|
|
1984
|
+
outputDir: outputBase,
|
|
1985
|
+
stepsBundlePath,
|
|
1986
|
+
workflowsBundlePath,
|
|
1987
|
+
webhookBundlePath,
|
|
1988
|
+
...{},
|
|
1989
|
+
manifestPath
|
|
1990
|
+
};
|
|
1991
|
+
}
|
|
1992
|
+
function hasWorkflowSourceFiles(directory) {
|
|
1993
|
+
const entries = fs4.readdirSync(directory, { withFileTypes: true });
|
|
1994
|
+
for (const entry of entries) {
|
|
1995
|
+
if (entry.isDirectory()) {
|
|
1996
|
+
if (hasWorkflowSourceFiles(path5.join(directory, entry.name))) {
|
|
1997
|
+
return true;
|
|
1998
|
+
}
|
|
1999
|
+
continue;
|
|
2000
|
+
}
|
|
2001
|
+
if (entry.isFile()) {
|
|
2002
|
+
const extension = path5.extname(entry.name).toLowerCase();
|
|
2003
|
+
if (WORKFLOW_SOURCE_EXTENSIONS.has(extension)) {
|
|
2004
|
+
return true;
|
|
2005
|
+
}
|
|
2006
|
+
}
|
|
2007
|
+
}
|
|
2008
|
+
return false;
|
|
2009
|
+
}
|
|
2010
|
+
var WORKFLOW_SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
2011
|
+
".ts",
|
|
2012
|
+
".tsx",
|
|
2013
|
+
".js",
|
|
2014
|
+
".jsx",
|
|
2015
|
+
".mjs",
|
|
2016
|
+
".cjs",
|
|
2017
|
+
".mts",
|
|
2018
|
+
".cts"
|
|
2019
|
+
]);
|
|
1854
2020
|
function timestamp() {
|
|
1855
2021
|
return (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19);
|
|
1856
2022
|
}
|