toolcraft 0.0.429 → 0.0.431
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/composition.json +3 -3
- package/dist/composition.json +3 -3
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/schema-standard.compile-check.d.ts +1 -0
- package/dist/schema-standard.compile-check.js +4 -0
- package/dist/schema.d.ts +2 -2
- package/dist/schema.js +1 -1
- package/node_modules/tiny-http-mcp-server/README.md +7 -0
- package/node_modules/tiny-http-mcp-server/dist/composition.json +2 -2
- package/node_modules/tiny-http-mcp-server/dist/fetch.d.ts +3 -3
- package/node_modules/tiny-http-mcp-server/dist/http-server.d.ts +2 -2
- package/node_modules/tiny-http-mcp-server/dist/index.d.ts +1 -1
- package/node_modules/tiny-http-mcp-server/package.json +1 -1
- package/node_modules/tiny-stdio-mcp-server/README.md +41 -3
- package/node_modules/tiny-stdio-mcp-server/dist/composition.json +1 -1
- package/node_modules/tiny-stdio-mcp-server/dist/core.d.ts +1 -1
- package/node_modules/tiny-stdio-mcp-server/dist/index.d.ts +1 -1
- package/node_modules/tiny-stdio-mcp-server/dist/protocol-server.d.ts +2 -2
- package/node_modules/tiny-stdio-mcp-server/dist/protocol-server.js +58 -45
- package/node_modules/tiny-stdio-mcp-server/dist/schema.d.ts +3 -0
- package/node_modules/tiny-stdio-mcp-server/dist/standard-schema.compile-check.d.ts +1 -0
- package/node_modules/tiny-stdio-mcp-server/dist/standard-schema.compile-check.js +15 -0
- package/node_modules/tiny-stdio-mcp-server/dist/tool-schema.d.ts +13 -0
- package/node_modules/tiny-stdio-mcp-server/dist/tool-schema.js +53 -0
- package/node_modules/tiny-stdio-mcp-server/dist/types.d.ts +3 -2
- package/node_modules/toolcraft-schema/README.md +51 -10
- package/node_modules/toolcraft-schema/dist/index.d.ts +35 -11
- package/node_modules/toolcraft-schema/dist/index.js +40 -20
- package/node_modules/toolcraft-schema/dist/json.d.ts +7 -1
- package/node_modules/toolcraft-schema/dist/json.js +3 -2
- package/node_modules/toolcraft-schema/dist/native-json-schema.d.ts +4 -1
- package/node_modules/toolcraft-schema/dist/native-json-schema.js +2 -1
- package/node_modules/toolcraft-schema/dist/oneof.d.ts +2 -1
- package/node_modules/toolcraft-schema/dist/oneof.js +3 -2
- package/node_modules/toolcraft-schema/dist/record.d.ts +2 -1
- package/node_modules/toolcraft-schema/dist/record.js +3 -2
- package/node_modules/toolcraft-schema/dist/standard.compile-check.d.ts +1 -0
- package/node_modules/toolcraft-schema/dist/standard.compile-check.js +20 -0
- package/node_modules/toolcraft-schema/dist/standard.d.ts +92 -0
- package/node_modules/toolcraft-schema/dist/standard.js +38 -0
- package/node_modules/toolcraft-schema/dist/union.d.ts +2 -1
- package/node_modules/toolcraft-schema/dist/union.js +3 -2
- package/node_modules/toolcraft-schema/package.json +1 -1
- package/package.json +2 -2
package/composition.json
CHANGED
|
@@ -98,7 +98,7 @@
|
|
|
98
98
|
},
|
|
99
99
|
{
|
|
100
100
|
"name": "tiny-http-mcp-server",
|
|
101
|
-
"version": "0.1.
|
|
101
|
+
"version": "0.1.94",
|
|
102
102
|
"license": "MIT"
|
|
103
103
|
},
|
|
104
104
|
{
|
|
@@ -113,7 +113,7 @@
|
|
|
113
113
|
},
|
|
114
114
|
{
|
|
115
115
|
"name": "toolcraft",
|
|
116
|
-
"version": "0.0.
|
|
116
|
+
"version": "0.0.431",
|
|
117
117
|
"license": "MIT"
|
|
118
118
|
},
|
|
119
119
|
{
|
|
@@ -123,7 +123,7 @@
|
|
|
123
123
|
},
|
|
124
124
|
{
|
|
125
125
|
"name": "toolcraft-schema",
|
|
126
|
-
"version": "0.0.
|
|
126
|
+
"version": "0.0.431",
|
|
127
127
|
"license": "MIT"
|
|
128
128
|
},
|
|
129
129
|
{
|
package/dist/composition.json
CHANGED
|
@@ -98,7 +98,7 @@
|
|
|
98
98
|
},
|
|
99
99
|
{
|
|
100
100
|
"name": "tiny-http-mcp-server",
|
|
101
|
-
"version": "0.1.
|
|
101
|
+
"version": "0.1.94",
|
|
102
102
|
"license": "MIT"
|
|
103
103
|
},
|
|
104
104
|
{
|
|
@@ -113,7 +113,7 @@
|
|
|
113
113
|
},
|
|
114
114
|
{
|
|
115
115
|
"name": "toolcraft",
|
|
116
|
-
"version": "0.0.
|
|
116
|
+
"version": "0.0.431",
|
|
117
117
|
"license": "MIT"
|
|
118
118
|
},
|
|
119
119
|
{
|
|
@@ -123,7 +123,7 @@
|
|
|
123
123
|
},
|
|
124
124
|
{
|
|
125
125
|
"name": "toolcraft-schema",
|
|
126
|
-
"version": "0.0.
|
|
126
|
+
"version": "0.0.431",
|
|
127
127
|
"license": "MIT"
|
|
128
128
|
},
|
|
129
129
|
{
|
package/dist/index.d.ts
CHANGED
|
@@ -247,7 +247,7 @@ export declare function cloneCommandNode<TNode extends CommandNode<any>>(node: T
|
|
|
247
247
|
export declare function cloneCommandNode<TServices extends object>(node: CommandNode<TServices>, scopeOverride: Scope[]): CommandNode<TServices>;
|
|
248
248
|
export declare function getCommandSourcePath(command: Command<any, any, any, any>): string | undefined;
|
|
249
249
|
export declare function hasMcpProxyConfig(group: Group<any>): boolean;
|
|
250
|
-
export { S, toJsonSchema } from "./schema.js";
|
|
250
|
+
export { S, toJsonSchema, withStandardSchema } from "./schema.js";
|
|
251
251
|
export { AuthenticationError, BadRequestError, ClientError, ConflictError, HttpError, InternalServerError, NotFoundError, PermissionDeniedError, RateLimitError, ServerError, ServiceUnavailableError, UnprocessableEntityError, createHttpError } from "./http-errors.js";
|
|
252
252
|
export type { HttpErrorRequest, HttpErrorResponse } from "./http-errors.js";
|
|
253
253
|
export { ApprovalDeclinedError, ToolcraftBugError, UserError, isUserError };
|
|
@@ -260,5 +260,5 @@ export type { PackageMetadata } from "./package-metadata.js";
|
|
|
260
260
|
export type { FileChangeRendererOptions, FileChangeResult } from "./file-change-renderer.js";
|
|
261
261
|
export type { FileChange, FileChangeDisplayMode, FileChangeKind } from "toolcraft-design";
|
|
262
262
|
export type { DiagnosticLogEvent, LogLevel, RuntimeLogger, RuntimeLoggerInput } from "./runtime-logging.js";
|
|
263
|
-
export type { AnySchema, ArraySchema, BooleanSchema, CliMissingParameterChoice, CliMissingParameterContext, CliMissingParameterResolution, CliOutputMode, CliSchemaOptions, EnumSchema, JsonSchema, JsonSchemaDocument, JsonSchemaDocumentOptions, JsonValue, JsonValueSchema, NumberSchema, ObjectSchema, OneOfSchema, OptionalSchema, RecordSchema, SchemaBase, Static, StringSchema, UnionSchema, ValidationIssue, ValidationOptions, ValidationResult } from "./schema.js";
|
|
263
|
+
export type { AnySchema, ArraySchema, BooleanSchema, CliMissingParameterChoice, CliMissingParameterContext, CliMissingParameterResolution, CliOutputMode, CliSchemaOptions, EnumSchema, JsonSchema, JsonSchemaDocument, JsonSchemaDocumentOptions, JsonSchemaOptions, Input, Output, StandardSchema, Standardized, StandardIssue, StandardResult, StandardJsonSchemaOptions, JsonValue, JsonValueSchema, NumberSchema, ObjectSchema, OneOfSchema, OptionalSchema, RecordSchema, SchemaBase, Static, StringSchema, UnionSchema, ValidationIssue, ValidationOptions, ValidationResult } from "./schema.js";
|
|
264
264
|
export type { HumanInLoopConfig, HumanInLoopPending, HumanInLoopRuntime };
|
package/dist/index.js
CHANGED
|
@@ -564,7 +564,7 @@ export function hasMcpProxyConfig(group) {
|
|
|
564
564
|
const children = config?.children ?? group.children;
|
|
565
565
|
return children.some((child) => child.kind === "group" && hasMcpProxyConfig(child));
|
|
566
566
|
}
|
|
567
|
-
export { S, toJsonSchema } from "./schema.js";
|
|
567
|
+
export { S, toJsonSchema, withStandardSchema } from "./schema.js";
|
|
568
568
|
export { AuthenticationError, BadRequestError, ClientError, ConflictError, HttpError, InternalServerError, NotFoundError, PermissionDeniedError, RateLimitError, ServerError, ServiceUnavailableError, UnprocessableEntityError, createHttpError } from "./http-errors.js";
|
|
569
569
|
export { ApprovalDeclinedError, ToolcraftBugError, UserError, isUserError };
|
|
570
570
|
export { suggest } from "./suggest.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/schema.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { Json, OneOf, Record, S, Union, toJsonSchema, toJsonSchemaDocument, validate } from "toolcraft-schema";
|
|
2
|
-
export type { AnySchema, ArraySchema, BooleanSchema, CliMissingParameterChoice, CliMissingParameterContext, CliMissingParameterResolution, CliOutputMode, CliSchemaOptions, EnumSchema, JsonSchema, JsonSchemaDocument, JsonSchemaDocumentOptions, JsonValue, JsonValueSchema, NumberSchema, ObjectSchema, OneOfSchema, OptionalSchema, RecordSchema, SchemaBase, Static, StringSchema, UnionSchema, ValidationIssue, ValidationOptions, ValidationResult } from "toolcraft-schema";
|
|
1
|
+
export { Json, OneOf, Record, S, Union, toJsonSchema, toJsonSchemaDocument, validate, withStandardSchema } from "toolcraft-schema";
|
|
2
|
+
export type { AnySchema, ArraySchema, BooleanSchema, CliMissingParameterChoice, CliMissingParameterContext, CliMissingParameterResolution, CliOutputMode, CliSchemaOptions, EnumSchema, JsonSchema, JsonSchemaDocument, JsonSchemaDocumentOptions, JsonSchemaOptions, Input, Output, StandardSchema, Standardized, StandardIssue, StandardResult, StandardJsonSchemaOptions, JsonValue, JsonValueSchema, NumberSchema, ObjectSchema, OneOfSchema, OptionalSchema, RecordSchema, SchemaBase, Static, StringSchema, UnionSchema, ValidationIssue, ValidationOptions, ValidationResult } from "toolcraft-schema";
|
package/dist/schema.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { Json, OneOf, Record, S, Union, toJsonSchema, toJsonSchemaDocument, validate } from "toolcraft-schema";
|
|
1
|
+
export { Json, OneOf, Record, S, Union, toJsonSchema, toJsonSchemaDocument, validate, withStandardSchema } from "toolcraft-schema";
|
|
@@ -73,6 +73,13 @@ By default, programmatic `listenHttp()` uses:
|
|
|
73
73
|
|
|
74
74
|
`path` is normalized, so `"mcp"` and `"/mcp"` serve the same endpoint.
|
|
75
75
|
|
|
76
|
+
The same `.tool()` and `.registerTool()` APIs accept Toolcraft schemas and
|
|
77
|
+
Zod 4.5.4 schemas directly through Standard Schema and Standard JSON Schema.
|
|
78
|
+
No adapter or Zod dependency is added by this package. Handlers receive inferred,
|
|
79
|
+
parsed arguments with defaults and transforms applied; asynchronous refinements
|
|
80
|
+
are awaited. This also works with `createFetchServer` from
|
|
81
|
+
`tiny-http-mcp-server/fetch`.
|
|
82
|
+
|
|
76
83
|
### CLI
|
|
77
84
|
|
|
78
85
|
The package ships a `tiny-http-mcp-server` binary:
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
},
|
|
19
19
|
{
|
|
20
20
|
"name": "tiny-http-mcp-server",
|
|
21
|
-
"version": "0.1.
|
|
21
|
+
"version": "0.1.94",
|
|
22
22
|
"license": "MIT"
|
|
23
23
|
},
|
|
24
24
|
{
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
},
|
|
29
29
|
{
|
|
30
30
|
"name": "tiny-stdio-mcp-server",
|
|
31
|
-
"version": "0.1.
|
|
31
|
+
"version": "0.1.29",
|
|
32
32
|
"license": "MIT"
|
|
33
33
|
},
|
|
34
34
|
{
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { type CallToolResult, type HandlerRequestContext, type InputRequiredResult, type ServerOptions, type ToolDefinition, type ToolReturn, type
|
|
1
|
+
import { type CallToolResult, type HandlerRequestContext, type InputRequiredResult, type ServerOptions, type ToolDefinition, type ToolReturn, type ToolInputSchema, type ToolOutputSchema } from "tiny-stdio-mcp-server/core";
|
|
2
2
|
export { defineSchema, ToolError } from "tiny-stdio-mcp-server/core";
|
|
3
|
-
export type { CallToolResult, TypedSchema, TypedOutputSchema } from "tiny-stdio-mcp-server/core";
|
|
3
|
+
export type { CallToolResult, TypedSchema, TypedOutputSchema, ToolInputSchema, ToolOutputSchema } from "tiny-stdio-mcp-server/core";
|
|
4
4
|
export interface FetchServerOptions extends ServerOptions {
|
|
5
5
|
/** Defaults to 1 MiB. Enforced while reading the stream. */
|
|
6
6
|
maxRequestBytes?: number;
|
|
@@ -15,7 +15,7 @@ export interface FetchToolContext<TContext> extends HandlerRequestContext {
|
|
|
15
15
|
}
|
|
16
16
|
export type FetchToolHandler<TIn, TContext, TOut = ToolReturn> = (input: TIn, context: FetchToolContext<TContext>) => TOut | CallToolResult | InputRequiredResult | Promise<TOut | CallToolResult | InputRequiredResult>;
|
|
17
17
|
export interface FetchServer<TContext = undefined> {
|
|
18
|
-
tool<TIn, TOut = never>(name: string, description: string, schema:
|
|
18
|
+
tool<TIn, TOut = never>(name: string, description: string, schema: ToolInputSchema<TIn>, handler: FetchToolHandler<TIn, TContext, TOut>, outputSchema?: ToolOutputSchema<TOut>): FetchServer<TContext>;
|
|
19
19
|
registerTool<TIn, TOut = never>(definition: Omit<ToolDefinition<TIn, TOut>, "handler">, handler: FetchToolHandler<TIn, TContext, TOut>): FetchServer<TContext>;
|
|
20
20
|
fetch(request: Request, ...context: undefined extends TContext ? [context?: TContext] : [context: TContext]): Promise<Response>;
|
|
21
21
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type IncomingMessage, type ServerResponse } from "node:http";
|
|
2
|
-
import { type Server, type ServerOptions, type ToolDefinition, type CallToolResult, type InputRequiredResult, type HandlerRequestContext, type ToolReturn, type
|
|
2
|
+
import { type Server, type ServerOptions, type ToolDefinition, type CallToolResult, type InputRequiredResult, type HandlerRequestContext, type ToolReturn, type ToolInputSchema, type ToolOutputSchema } from "tiny-stdio-mcp-server";
|
|
3
3
|
import { type AuthenticatedIncomingMessage, type TokenVerifier, type VerifiedAccessToken, type RequestAuthInfo } from "./auth.js";
|
|
4
4
|
import { type HttpObservabilityEvent, type StreamableHttpTransportOptions } from "./http-transport.js";
|
|
5
5
|
export interface ProtectedResourceMetadataOptions {
|
|
@@ -33,7 +33,7 @@ export interface HttpServerHandle {
|
|
|
33
33
|
closeAllConnections(): void;
|
|
34
34
|
}
|
|
35
35
|
export interface HttpServer extends Omit<Server, "tool" | "registerTool"> {
|
|
36
|
-
tool<TIn, TOut = never>(name: string, description: string, inputSchema:
|
|
36
|
+
tool<TIn, TOut = never>(name: string, description: string, inputSchema: ToolInputSchema<TIn>, handler: HttpToolHandler<TIn, TOut>, outputSchema?: ToolOutputSchema<TOut>): HttpServer;
|
|
37
37
|
registerTool<TIn, TOut = never>(definition: Omit<ToolDefinition<TIn, TOut>, "handler">, handler: HttpToolHandler<TIn, TOut>): HttpServer;
|
|
38
38
|
listenHttp(options?: HttpListenOptions): Promise<HttpServerHandle>;
|
|
39
39
|
handleRequest(req: IncomingMessage, res: ServerResponse): Promise<void>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { createServer, defineSchema, Image, Audio, File, toContentBlocks, fileTypeFromBuffer, JSON_RPC_ERROR_CODES, ToolError } from "tiny-stdio-mcp-server";
|
|
2
|
-
export type { Server, MessageRequestContext, MessageSession, MessageSessionContext, TypedSchema, TypedOutputSchema, ImageContent, AudioContent, EmbeddedResource, TextResourceContents, BlobResourceContents, ContentBlock, TextContent, FileTypeResult, ToolReturn, ServerOptions, ToolHandler, HandlerRequestContext, InputRequiredResult, ToolDefinition, Tool, ToolAnnotations, ToolExecution, Icon, ContentAnnotations, ResourceLink, CallToolResult, PromptContentItem, PromptArgument, Prompt, PromptMessage, GetPromptResult, PromptHandler, PromptDefinition, Resource, ResourceTemplate, ResourceContents, ReadResourceResult, ResourceHandler, ResourceDefinition, ResourceTemplateDefinition, HandleResult, ContentItem, JSONSchema, OutputSchema, JSONSchemaProperty, Transport, SDKTransport, JSONRPCRequest, JSONRPCResponse, JSONRPCError, JSONRPCMessage, JSONRPCNotification, InitializeResult, DiscoverResult } from "tiny-stdio-mcp-server";
|
|
2
|
+
export type { Server, MessageRequestContext, MessageSession, MessageSessionContext, TypedSchema, TypedOutputSchema, ToolInputSchema, ToolOutputSchema, ImageContent, AudioContent, EmbeddedResource, TextResourceContents, BlobResourceContents, ContentBlock, TextContent, FileTypeResult, ToolReturn, ServerOptions, ToolHandler, HandlerRequestContext, InputRequiredResult, ToolDefinition, Tool, ToolAnnotations, ToolExecution, Icon, ContentAnnotations, ResourceLink, CallToolResult, PromptContentItem, PromptArgument, Prompt, PromptMessage, GetPromptResult, PromptHandler, PromptDefinition, Resource, ResourceTemplate, ResourceContents, ReadResourceResult, ResourceHandler, ResourceDefinition, ResourceTemplateDefinition, HandleResult, ContentItem, JSONSchema, OutputSchema, JSONSchemaProperty, Transport, SDKTransport, JSONRPCRequest, JSONRPCResponse, JSONRPCError, JSONRPCMessage, JSONRPCNotification, InitializeResult, DiscoverResult } from "tiny-stdio-mcp-server";
|
|
3
3
|
export { createExpressMiddleware, createExpressOAuthHandlers, createProtectedResourceMetadataRouter } from "./express-middleware.js";
|
|
4
4
|
export type { CreateExpressOAuthHandlersOptions } from "./express-middleware.js";
|
|
5
5
|
export { createHttpServer, createProtectedResourceMetadataDocument } from "./http-server.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# tiny-stdio-mcp-server
|
|
2
2
|
|
|
3
|
-
Minimal [Model Context Protocol](https://modelcontextprotocol.io) server for Node.js.
|
|
3
|
+
Minimal [Model Context Protocol](https://modelcontextprotocol.io) server for Node.js. Type-safe tool definitions, rich content helpers for images/audio/files.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
@@ -89,14 +89,52 @@ server.tool(
|
|
|
89
89
|
);
|
|
90
90
|
```
|
|
91
91
|
|
|
92
|
-
|
|
92
|
+
Object output schemas work across MCP versions; modern MCP also supports other JSON output types. Otherwise, supported JSON Schema keywords are accepted, including composition keywords, nullable type unions, and local `$defs`/`$ref` references. Input and output schemas compile synchronously during `.tool()` or `.registerTool()` registration, so malformed schemas throw immediately instead of failing on the first tool call.
|
|
93
93
|
|
|
94
|
-
Successful structured results must satisfy `outputSchema`. Validation failures use JSON-RPC `-32602` for inputs and `-32603` for outputs, with
|
|
94
|
+
Successful structured results must satisfy `outputSchema`. Validation failures use JSON-RPC `-32602` for inputs and `-32603` for outputs, with formatted validation details in the message and the issue array in `error.data`. Explicit handler results with `isError: true` are passed through unchanged and are exempt from structured-content and output-schema validation.
|
|
95
95
|
|
|
96
96
|
Tools whose natural result is prose, images, audio, files, or other content blocks should omit `outputSchema` and keep returning content.
|
|
97
97
|
|
|
98
98
|
Handlers can throw `ToolError` to return a JSON-RPC tool error with a specific code, message, and optional structured `data` payload. The server forwards that `data` field in the JSON-RPC error response so clients can inspect machine-readable failure details.
|
|
99
99
|
|
|
100
|
+
### Standard schemas, including Zod
|
|
101
|
+
|
|
102
|
+
Pass schemas implementing Standard Schema v1 and Standard JSON Schema v1
|
|
103
|
+
straight to `.tool()` or `.registerTool()`. Toolcraft schemas and Zod 4.5.4
|
|
104
|
+
support both interfaces. Existing `defineSchema` and raw JSON Schema inputs
|
|
105
|
+
continue to work on the same server.
|
|
106
|
+
|
|
107
|
+
```ts
|
|
108
|
+
import { z } from "zod"; // Your application's existing dependency
|
|
109
|
+
import { createServer } from "tiny-stdio-mcp-server";
|
|
110
|
+
|
|
111
|
+
createServer({ name: "search", version: "1" }).tool(
|
|
112
|
+
"search",
|
|
113
|
+
"Search",
|
|
114
|
+
z.object({ query: z.string(), limit: z.number().default(10) }),
|
|
115
|
+
({ query, limit }) => `${query}: ${limit}`
|
|
116
|
+
);
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Tiny MCP has no Zod dependency, peer dependency, imports, or adapter setup.
|
|
120
|
+
Detection uses the standard interfaces. Older libraries exposing validation
|
|
121
|
+
without JSON Schema conversion fail clearly during registration.
|
|
122
|
+
|
|
123
|
+
Discovery uses the schema's input JSON Schema and, when supplied, its output
|
|
124
|
+
JSON Schema. Runtime parsing uses the original library, preserving defaults,
|
|
125
|
+
coercions, transforms, refinements, and asynchronous validation. Handler arguments
|
|
126
|
+
are inferred from parsed output; a handler's return value is checked against the
|
|
127
|
+
output schema's accepted input. Output parsing runs once before structured content
|
|
128
|
+
and fallback text are produced. Explicit error results skip output parsing.
|
|
129
|
+
|
|
130
|
+
Input wire schemas must describe objects. Output schemas may describe any JSON
|
|
131
|
+
value for modern MCP; older clients receive object structured content or text
|
|
132
|
+
fallbacks for other values. Conversion failures occur at registration. Custom
|
|
133
|
+
refinements remain runtime checks and cannot always appear in discovery JSON
|
|
134
|
+
Schema. Async parsing shares the tool timeout and concurrency limits.
|
|
135
|
+
`validateToolArguments: false` disables input parsing, including defaults and
|
|
136
|
+
transforms; handlers then receive the original arguments.
|
|
137
|
+
|
|
100
138
|
### `.listen()`
|
|
101
139
|
|
|
102
140
|
Start listening on stdin/stdout (standard MCP stdio transport).
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
export { createProtocolServer } from "./protocol-server.js";
|
|
3
3
|
export type { Server, MessageRequestContext, MessageSession } from "./protocol-server.js";
|
|
4
4
|
export { defineSchema } from "./schema.js";
|
|
5
|
-
export type { TypedSchema, TypedOutputSchema } from "./schema.js";
|
|
5
|
+
export type { TypedSchema, TypedOutputSchema, ToolInputSchema, ToolOutputSchema } from "./schema.js";
|
|
6
6
|
export { ToolError } from "./types.js";
|
|
7
7
|
export type { CallToolResult, HandlerRequestContext, InputRequiredResult, ServerOptions, ToolDefinition } from "./types.js";
|
|
8
8
|
export type { ToolReturn } from "./content/convert.js";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { createServer } from "./server.js";
|
|
2
2
|
export type { CustomMethodHandler, MessageHandler, MessageRequestContext, MessageSession, MessageSessionContext, Server } from "./server.js";
|
|
3
3
|
export { defineSchema } from "./schema.js";
|
|
4
|
-
export type { TypedSchema, TypedOutputSchema } from "./schema.js";
|
|
4
|
+
export type { TypedSchema, TypedOutputSchema, ToolInputSchema, ToolOutputSchema } from "./schema.js";
|
|
5
5
|
export { Image, Audio, File, toContentBlocks, fileTypeFromBuffer, DEFAULT_FROM_URL_MAX_BYTES } from "./content/index.js";
|
|
6
6
|
export type { ImageContent, AudioContent, EmbeddedResource, TextResourceContents, BlobResourceContents, ContentBlock, TextContent, FileTypeResult, FromUrlOptions } from "./content/index.js";
|
|
7
7
|
export type { ToolReturn } from "./content/index.js";
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type { ServerOptions, ToolDefinition, ToolHandler, HandleResult, Prompt, PromptHandler, Resource, ResourceHandler, ResourceTemplate, Transport, SDKTransport, JSONRPCNotification } from "./types.js";
|
|
2
|
-
import type {
|
|
2
|
+
import type { ToolInputSchema, ToolOutputSchema } from "./schema.js";
|
|
3
3
|
interface StdioRuntime {
|
|
4
4
|
readline: typeof import("node:readline");
|
|
5
5
|
StdioInput: typeof import("./stdio-input.js").StdioInput;
|
|
6
6
|
StdioOutput: typeof import("./stdio-output.js").StdioOutput;
|
|
7
7
|
}
|
|
8
8
|
export interface Server {
|
|
9
|
-
tool<TIn, TOut = never>(name: string, description: string, inputSchema:
|
|
9
|
+
tool<TIn, TOut = never>(name: string, description: string, inputSchema: ToolInputSchema<TIn>, handler: ToolHandler<TIn, TOut>, outputSchema?: ToolOutputSchema<TOut>): Server;
|
|
10
10
|
registerTool<TIn, TOut = never>(definition: Omit<ToolDefinition<TIn, TOut>, "handler">, handler: ToolHandler<TIn, TOut>): Server;
|
|
11
11
|
prompt(definition: Prompt, handler: PromptHandler): Server;
|
|
12
12
|
resource(definition: Resource, handler: ResourceHandler): Server;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { prepareToolSchema, formatToolIssues } from "./tool-schema.js";
|
|
2
2
|
import { JSON_RPC_ERROR_CODES, ToolError } from "./types.js";
|
|
3
3
|
import { parseMessage, formatSuccessResponse, formatErrorResponse, isRequestId } from "./jsonrpc.js";
|
|
4
4
|
import { parseUriTemplate } from "./uri-template.js";
|
|
@@ -38,15 +38,6 @@ function createLifecycleState(listener, supportNotifications, supportResourceSub
|
|
|
38
38
|
listener
|
|
39
39
|
};
|
|
40
40
|
}
|
|
41
|
-
function compileToolSchema(schema) {
|
|
42
|
-
try {
|
|
43
|
-
return compileJsonSchema(schema);
|
|
44
|
-
}
|
|
45
|
-
catch (error) {
|
|
46
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
47
|
-
throw new Error(`schema is invalid: ${message}`, { cause: error });
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
41
|
export function createProtocolServer(options, stdio) {
|
|
51
42
|
if (options.toolCallTimeoutMs !== undefined &&
|
|
52
43
|
(!Number.isInteger(options.toolCallTimeoutMs) || options.toolCallTimeoutMs <= 0)) {
|
|
@@ -215,15 +206,15 @@ export function createProtocolServer(options, stdio) {
|
|
|
215
206
|
if (headerError !== undefined)
|
|
216
207
|
return { error: { code: -32020, message: headerError } };
|
|
217
208
|
}
|
|
218
|
-
|
|
219
|
-
if (options.validateToolArguments !== false && !
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
209
|
+
// Raw JSON Schema validation is synchronous and can reject before taking a queue slot.
|
|
210
|
+
if (options.validateToolArguments !== false && !tool.inputValidator.standard) {
|
|
211
|
+
const validation = tool.inputValidator.validate(toolArgs);
|
|
212
|
+
if (validation.issues !== undefined)
|
|
213
|
+
return { error: {
|
|
214
|
+
code: JSON_RPC_ERROR_CODES.INVALID_PARAMS,
|
|
215
|
+
message: `Invalid tool arguments: ${formatToolIssues(validation.issues)}`,
|
|
216
|
+
data: validation.issues
|
|
217
|
+
} };
|
|
227
218
|
}
|
|
228
219
|
try {
|
|
229
220
|
let handlerResult;
|
|
@@ -242,7 +233,20 @@ export function createProtocolServer(options, stdio) {
|
|
|
242
233
|
const release = await toolAdmission.acquire(admissionSignal);
|
|
243
234
|
try {
|
|
244
235
|
admissionSignal.throwIfAborted();
|
|
245
|
-
|
|
236
|
+
let parsedArgs = toolArgs;
|
|
237
|
+
if (options.validateToolArguments !== false && tool.inputValidator.standard) {
|
|
238
|
+
const inputValidation = await tool.inputValidator.validate(toolArgs);
|
|
239
|
+
if (inputValidation.issues !== undefined) {
|
|
240
|
+
throw new ToolError(JSON_RPC_ERROR_CODES.INVALID_PARAMS, `Invalid tool arguments: ${formatToolIssues(inputValidation.issues)}`, inputValidation.issues);
|
|
241
|
+
}
|
|
242
|
+
parsedArgs = inputValidation.value;
|
|
243
|
+
}
|
|
244
|
+
admissionSignal.throwIfAborted();
|
|
245
|
+
const returned = await tool.handler(parsedArgs, { ...handlerContext, signal: admissionSignal });
|
|
246
|
+
admissionSignal.throwIfAborted();
|
|
247
|
+
if (modern && isInputRequiredResult(returned))
|
|
248
|
+
return returned;
|
|
249
|
+
return await normalizeValidatedToolResult(returned, tool, modern);
|
|
246
250
|
}
|
|
247
251
|
finally {
|
|
248
252
|
release();
|
|
@@ -274,15 +278,7 @@ export function createProtocolServer(options, stdio) {
|
|
|
274
278
|
lifecycle.admissions.delete(admissionController);
|
|
275
279
|
sessionSignal.removeEventListener("abort", cancelAdmission);
|
|
276
280
|
}
|
|
277
|
-
|
|
278
|
-
return { result: handlerResult };
|
|
279
|
-
const outputSchema = modern || tool.outputSchema?.type === "object" ? tool.outputSchema : undefined;
|
|
280
|
-
const result = normalizeToolResult(handlerResult, tool.outputSchema, modern);
|
|
281
|
-
const outputValidation = outputSchema === undefined ? undefined : tool.outputValidator?.validate(result.structuredContent);
|
|
282
|
-
if (result.isError !== true && outputValidation !== undefined && !outputValidation.ok) {
|
|
283
|
-
throw new ToolError(JSON_RPC_ERROR_CODES.INTERNAL_ERROR, `Invalid structured tool result: ${formatIssues(outputValidation.issues)}`, outputValidation.issues);
|
|
284
|
-
}
|
|
285
|
-
return { result };
|
|
281
|
+
return { result: handlerResult };
|
|
286
282
|
}
|
|
287
283
|
catch (err) {
|
|
288
284
|
if (err instanceof ToolError) {
|
|
@@ -614,15 +610,13 @@ export function createProtocolServer(options, stdio) {
|
|
|
614
610
|
if (tools.has(name)) {
|
|
615
611
|
throw new Error(`Tool already registered: ${name}`);
|
|
616
612
|
}
|
|
617
|
-
const
|
|
618
|
-
const
|
|
619
|
-
const inputValidator = compileToolSchema(inputSchemaSnapshot);
|
|
613
|
+
const inputValidator = prepareToolSchema(inputSchema, "input");
|
|
614
|
+
const inputSchemaSnapshot = inputValidator.schema;
|
|
620
615
|
assertObjectRootSchema(inputSchemaSnapshot, "inputSchema");
|
|
621
|
-
|
|
622
|
-
|
|
616
|
+
const outputValidator = outputSchema === undefined ? undefined : prepareToolSchema(outputSchema, "output");
|
|
617
|
+
const outputSchemaSnapshot = outputValidator?.schema;
|
|
618
|
+
if (outputSchemaSnapshot !== undefined)
|
|
623
619
|
assertOutputSchema(outputSchemaSnapshot);
|
|
624
|
-
outputValidator = compileToolSchema(outputSchemaSnapshot);
|
|
625
|
-
}
|
|
626
620
|
tools.set(name, {
|
|
627
621
|
name,
|
|
628
622
|
description,
|
|
@@ -640,19 +634,18 @@ export function createProtocolServer(options, stdio) {
|
|
|
640
634
|
if (tools.has(definition.name)) {
|
|
641
635
|
throw new Error(`Tool already registered: ${definition.name}`);
|
|
642
636
|
}
|
|
643
|
-
const
|
|
644
|
-
const
|
|
645
|
-
const inputValidator =
|
|
637
|
+
const { inputSchema: sourceInput, outputSchema: sourceOutput, ...metadata } = definition;
|
|
638
|
+
const descriptor = structuredClone(metadata);
|
|
639
|
+
const inputValidator = prepareToolSchema(sourceInput, "input");
|
|
640
|
+
const inputSchema = inputValidator.schema;
|
|
646
641
|
assertObjectRootSchema(inputSchema, "inputSchema");
|
|
647
|
-
|
|
648
|
-
if (
|
|
649
|
-
|
|
650
|
-
assertOutputSchema(descriptor.outputSchema);
|
|
651
|
-
outputValidator = compileToolSchema(descriptor.outputSchema);
|
|
652
|
-
}
|
|
642
|
+
const outputValidator = sourceOutput === undefined ? undefined : prepareToolSchema(sourceOutput, "output");
|
|
643
|
+
if (outputValidator !== undefined)
|
|
644
|
+
assertOutputSchema(outputValidator.schema);
|
|
653
645
|
tools.set(definition.name, {
|
|
654
646
|
...descriptor,
|
|
655
647
|
inputSchema,
|
|
648
|
+
...(outputValidator === undefined ? {} : { outputSchema: outputValidator.schema }),
|
|
656
649
|
handler: handler,
|
|
657
650
|
inputValidator,
|
|
658
651
|
parameterHeaders: getParameterHeaders(inputSchema),
|
|
@@ -987,6 +980,26 @@ function isCallToolResult(value, modern) {
|
|
|
987
980
|
value.isError !== undefined &&
|
|
988
981
|
typeof value.isError !== "boolean");
|
|
989
982
|
}
|
|
983
|
+
async function normalizeValidatedToolResult(returned, tool, modern) {
|
|
984
|
+
const validator = tool.outputValidator;
|
|
985
|
+
if (validator?.standard && !(isCallToolResult(returned, modern) && returned.isError === true)) {
|
|
986
|
+
const envelope = isCallToolResult(returned, modern) ? returned : undefined;
|
|
987
|
+
const parsed = await validator.validate(envelope === undefined ? returned : envelope.structuredContent);
|
|
988
|
+
if (parsed.issues !== undefined) {
|
|
989
|
+
throw new ToolError(JSON_RPC_ERROR_CODES.INTERNAL_ERROR, `Invalid structured tool result: ${formatToolIssues(parsed.issues)}`, parsed.issues);
|
|
990
|
+
}
|
|
991
|
+
returned = envelope === undefined ? parsed.value : { ...envelope, structuredContent: parsed.value };
|
|
992
|
+
}
|
|
993
|
+
const result = normalizeToolResult(returned, tool.outputSchema, modern);
|
|
994
|
+
if (result.isError !== true && validator !== undefined && !validator.standard &&
|
|
995
|
+
(modern || tool.outputSchema?.type === "object")) {
|
|
996
|
+
const validation = await validator.validate(result.structuredContent);
|
|
997
|
+
if (validation.issues !== undefined) {
|
|
998
|
+
throw new ToolError(JSON_RPC_ERROR_CODES.INTERNAL_ERROR, `Invalid structured tool result: ${formatToolIssues(validation.issues)}`, validation.issues);
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
1001
|
+
return result;
|
|
1002
|
+
}
|
|
990
1003
|
function normalizeToolResult(handlerResult, outputSchema, modern) {
|
|
991
1004
|
if (!modern && outputSchema !== undefined && outputSchema.type !== "object") {
|
|
992
1005
|
const result = normalizeToolResult(handlerResult, outputSchema, true);
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import type { JSONSchema, OutputSchema } from "./types.js";
|
|
2
|
+
import type { StandardSchema } from "toolcraft-schema";
|
|
3
|
+
export type ToolInputSchema<T> = TypedSchema<T> | StandardSchema<unknown, T>;
|
|
4
|
+
export type ToolOutputSchema<T> = TypedOutputSchema<T> | StandardSchema<T, unknown>;
|
|
2
5
|
type SchemaPropertyType = "string" | "number" | "integer" | "boolean" | "object" | "array";
|
|
3
6
|
interface SchemaPropertyDef {
|
|
4
7
|
type: SchemaPropertyType;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { S } from "toolcraft-schema";
|
|
2
|
+
import { createServer, defineSchema } from "./index.js";
|
|
3
|
+
const server = createServer({ name: "inference", version: "1" });
|
|
4
|
+
const schema = S.Object({ count: S.Optional(S.Number({ default: 10 })) });
|
|
5
|
+
server.tool("count", "Count", schema, ({ count }) => {
|
|
6
|
+
const result = count;
|
|
7
|
+
// @ts-expect-error The default produces a number, not a string.
|
|
8
|
+
const ignoredWrong = count;
|
|
9
|
+
return { count: result };
|
|
10
|
+
}, S.Object({ count: S.Number() }));
|
|
11
|
+
server.registerTool({ name: "registered", inputSchema: schema }, ({ count }) => String(count + 1));
|
|
12
|
+
server.tool("transform", "Transform", transformed, ({ count }) => count.toFixed());
|
|
13
|
+
server.tool("output", "Output", defineSchema({}), () => ({ count: "1" }), transformed);
|
|
14
|
+
// @ts-expect-error The output parser requires a string before transformation.
|
|
15
|
+
server.tool("invalid", "Invalid", defineSchema({}), () => ({ count: false }), transformed);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type StandardIssue, type StandardResult } from "toolcraft-schema";
|
|
2
|
+
import { type OutputSchema } from "./types.js";
|
|
3
|
+
export type PreparedToolSchema = {
|
|
4
|
+
schema: OutputSchema;
|
|
5
|
+
} & ({
|
|
6
|
+
standard: false;
|
|
7
|
+
validate(value: unknown): StandardResult<unknown>;
|
|
8
|
+
} | {
|
|
9
|
+
standard: true;
|
|
10
|
+
validate(value: unknown): StandardResult<unknown> | Promise<StandardResult<unknown>>;
|
|
11
|
+
});
|
|
12
|
+
export declare function prepareToolSchema(source: unknown, io: "input" | "output"): PreparedToolSchema;
|
|
13
|
+
export declare function formatToolIssues(issues: readonly StandardIssue[]): string;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { compileJsonSchema, normalizeLegacyNullability } from "toolcraft-schema";
|
|
2
|
+
import { ToolError, JSON_RPC_ERROR_CODES } from "./types.js";
|
|
3
|
+
export function prepareToolSchema(source, io) {
|
|
4
|
+
try {
|
|
5
|
+
let standard;
|
|
6
|
+
if (((typeof source === "object" && source !== null) || typeof source === "function") && "~standard" in source) {
|
|
7
|
+
standard = source["~standard"];
|
|
8
|
+
if (standard?.version !== 1 || typeof standard.validate !== "function") {
|
|
9
|
+
throw new Error("Expected Standard Schema v1 validation");
|
|
10
|
+
}
|
|
11
|
+
if (typeof standard.jsonSchema?.[io] !== "function") {
|
|
12
|
+
throw new Error("Expected Standard JSON Schema v1 conversion; upgrade the schema library or provide a JSON Schema");
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
const document = standard === undefined ? source : standard.jsonSchema[io]({ target: "draft-2020-12" });
|
|
16
|
+
if (typeof document !== "object" || document === null || Array.isArray(document)) {
|
|
17
|
+
throw new Error(`${io}Schema must be a JSON Schema object`);
|
|
18
|
+
}
|
|
19
|
+
const schema = normalizeLegacyNullability(document);
|
|
20
|
+
const compiled = compileJsonSchema(schema);
|
|
21
|
+
if (standard !== undefined)
|
|
22
|
+
return {
|
|
23
|
+
schema,
|
|
24
|
+
standard: true,
|
|
25
|
+
async validate(value) {
|
|
26
|
+
try {
|
|
27
|
+
return await standard.validate(value);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
throw new ToolError(JSON_RPC_ERROR_CODES.INTERNAL_ERROR, "Tool schema validation failed");
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
return {
|
|
35
|
+
schema,
|
|
36
|
+
standard: false,
|
|
37
|
+
validate(value) {
|
|
38
|
+
const result = compiled.validate(value);
|
|
39
|
+
return result.ok ? { value: result.value } : { issues: result.issues };
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
45
|
+
throw new Error(`${io} schema is invalid: ${message}`, { cause: error });
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
export function formatToolIssues(issues) {
|
|
49
|
+
return issues.map((issue) => {
|
|
50
|
+
const path = issue.path?.map((segment) => String(typeof segment === "object" ? segment.key : segment)).join("/");
|
|
51
|
+
return `${path ? `data/${path}` : "data"} ${issue.message}`;
|
|
52
|
+
}).join(", ");
|
|
53
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ToolInputSchema, ToolOutputSchema } from "./schema.js";
|
|
1
2
|
export interface JSONRPCRequest {
|
|
2
3
|
jsonrpc: "2.0";
|
|
3
4
|
id: string | number | null;
|
|
@@ -270,8 +271,8 @@ export interface ToolDefinition<T = Record<string, unknown>, TOut = ToolReturn>
|
|
|
270
271
|
name: string;
|
|
271
272
|
title?: string;
|
|
272
273
|
description?: string;
|
|
273
|
-
inputSchema:
|
|
274
|
-
outputSchema?:
|
|
274
|
+
inputSchema: ToolInputSchema<T>;
|
|
275
|
+
outputSchema?: ToolOutputSchema<TOut>;
|
|
275
276
|
annotations?: ToolAnnotations;
|
|
276
277
|
execution?: ToolExecution;
|
|
277
278
|
icons?: Icon[];
|