@outfitter/mcp 0.4.2 → 0.5.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 +130 -28
- package/dist/actions.d.ts +7 -2
- package/dist/actions.js +52 -5
- package/dist/core-tools.d.ts +7 -2
- package/dist/core-tools.js +140 -6
- package/dist/index.d.ts +14 -953
- package/dist/index.js +8 -959
- package/dist/internal/content-types.d.ts +2 -0
- package/dist/internal/content-types.js +1 -0
- package/dist/internal/log-config.d.ts +24 -0
- package/dist/internal/log-config.js +13 -0
- package/dist/internal/prompt-types.d.ts +3 -0
- package/dist/internal/prompt-types.js +1 -0
- package/dist/internal/resource-types.d.ts +4 -0
- package/dist/internal/resource-types.js +1 -0
- package/dist/internal/server-types.d.ts +7 -0
- package/dist/internal/server-types.js +20 -0
- package/dist/internal/tool-types.d.ts +2 -0
- package/dist/{shared/@outfitter/mcp-9m5hs2z0.js → internal/tool-types.js} +4 -16
- package/dist/internal/uri-template.d.ts +8 -0
- package/dist/internal/uri-template.js +7 -0
- package/dist/progress.d.ts +2 -0
- package/dist/progress.js +7 -0
- package/dist/schema.js +1 -1
- package/dist/server.d.ts +7 -2
- package/dist/server.js +6 -3
- package/dist/shared/@outfitter/{mcp-5b5726ga.d.ts → mcp-3hxaatj9.d.ts} +37 -6
- package/dist/shared/@outfitter/{mcp-zb3p61y9.d.ts → mcp-4s22693j.d.ts} +1 -1
- package/dist/shared/@outfitter/mcp-7btcghjj.d.ts +304 -0
- package/dist/shared/@outfitter/mcp-9ry52yg3.d.ts +187 -0
- package/dist/shared/@outfitter/mcp-dgwj3jna.d.ts +103 -0
- package/dist/shared/@outfitter/{mcp-5jcgb033.d.ts → mcp-f67dnr72.d.ts} +1 -1
- package/dist/shared/@outfitter/mcp-hw5wz4gb.js +1 -0
- package/dist/shared/@outfitter/mcp-knc1gq0g.d.ts +130 -0
- package/dist/shared/@outfitter/mcp-n9vzcp37.js +55 -0
- package/dist/shared/@outfitter/mcp-q5hr7227.d.ts +24 -0
- package/dist/shared/@outfitter/mcp-q70dtfj6.js +53 -0
- package/dist/shared/@outfitter/mcp-r27vbpc1.d.ts +45 -0
- package/dist/shared/@outfitter/mcp-s2vnhzav.js +2 -0
- package/dist/shared/@outfitter/{mcp-s3gfhcdk.d.ts → mcp-yf0w5cgh.d.ts} +1 -1
- package/dist/shared/@outfitter/{mcp-hh12tqfg.js → mcp-yf1n85e9.js} +79 -119
- package/dist/shared/@outfitter/mcp-zt2s3r38.js +33 -0
- package/dist/transport.d.ts +7 -2
- package/dist/transport.js +161 -5
- package/dist/types.d.ts +7 -2
- package/dist/types.js +1 -1
- package/package.json +33 -27
- package/dist/shared/@outfitter/mcp-fks4zt1z.d.ts +0 -699
- package/dist/shared/@outfitter/mcp-mzky3ck8.js +0 -165
- package/dist/shared/@outfitter/mcp-zmc7ht6z.js +0 -28
- package/dist/shared/@outfitter/mcp-zv3ej45k.js +0 -143
- package/dist/shared/@outfitter/mcp-zy7b487d.js +0 -5
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { CompletionHandler } from "./mcp-dgwj3jna.js";
|
|
2
|
+
import { ContentAnnotations } from "./mcp-q5hr7227.js";
|
|
3
|
+
import { HandlerContext, OutfitterError, Result } from "@outfitter/contracts";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
/**
|
|
6
|
+
* Text content returned from a resource read.
|
|
7
|
+
*/
|
|
8
|
+
interface TextResourceContent {
|
|
9
|
+
/** Optional content annotations */
|
|
10
|
+
annotations?: ContentAnnotations;
|
|
11
|
+
/** Optional MIME type */
|
|
12
|
+
mimeType?: string;
|
|
13
|
+
/** Text content */
|
|
14
|
+
text: string;
|
|
15
|
+
/** Resource URI */
|
|
16
|
+
uri: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Binary (base64-encoded) content returned from a resource read.
|
|
20
|
+
*/
|
|
21
|
+
interface BlobResourceContent {
|
|
22
|
+
/** Optional content annotations */
|
|
23
|
+
annotations?: ContentAnnotations;
|
|
24
|
+
/** Base64-encoded binary content */
|
|
25
|
+
blob: string;
|
|
26
|
+
/** Optional MIME type */
|
|
27
|
+
mimeType?: string;
|
|
28
|
+
/** Resource URI */
|
|
29
|
+
uri: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Content returned from reading a resource.
|
|
33
|
+
*/
|
|
34
|
+
type ResourceContent = TextResourceContent | BlobResourceContent;
|
|
35
|
+
/**
|
|
36
|
+
* Handler for reading a resource's content.
|
|
37
|
+
*
|
|
38
|
+
* @param uri - The resource URI being read
|
|
39
|
+
* @param ctx - Handler context with logger and requestId
|
|
40
|
+
* @returns Array of resource content items
|
|
41
|
+
*/
|
|
42
|
+
type ResourceReadHandler = (uri: string, ctx: HandlerContext) => Promise<Result<ResourceContent[], OutfitterError>>;
|
|
43
|
+
/**
|
|
44
|
+
* Definition of an MCP resource that can be read by clients.
|
|
45
|
+
*
|
|
46
|
+
* Resources represent data that clients can access, such as files,
|
|
47
|
+
* database records, or API responses.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```typescript
|
|
51
|
+
* const configResource: ResourceDefinition = {
|
|
52
|
+
* uri: "file:///etc/app/config.json",
|
|
53
|
+
* name: "Application Config",
|
|
54
|
+
* description: "Main application configuration file",
|
|
55
|
+
* mimeType: "application/json",
|
|
56
|
+
* handler: async (uri, ctx) => {
|
|
57
|
+
* const content = await readFile(uri);
|
|
58
|
+
* return Result.ok([{ uri, text: content }]);
|
|
59
|
+
* },
|
|
60
|
+
* };
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
interface ResourceDefinition {
|
|
64
|
+
/**
|
|
65
|
+
* Optional description of the resource.
|
|
66
|
+
* Provides additional context about the resource contents.
|
|
67
|
+
*/
|
|
68
|
+
description?: string;
|
|
69
|
+
/**
|
|
70
|
+
* Optional handler for reading the resource content.
|
|
71
|
+
* If not provided, the resource is metadata-only.
|
|
72
|
+
*/
|
|
73
|
+
handler?: ResourceReadHandler;
|
|
74
|
+
/**
|
|
75
|
+
* Optional MIME type of the resource content.
|
|
76
|
+
* Helps clients understand how to process the resource.
|
|
77
|
+
*/
|
|
78
|
+
mimeType?: string;
|
|
79
|
+
/**
|
|
80
|
+
* Human-readable resource name.
|
|
81
|
+
* Displayed to users in resource listings.
|
|
82
|
+
*/
|
|
83
|
+
name: string;
|
|
84
|
+
/**
|
|
85
|
+
* Unique resource URI.
|
|
86
|
+
* Must be a valid URI (file://, https://, custom://, etc.).
|
|
87
|
+
*/
|
|
88
|
+
uri: string;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Handler for reading a resource template's content.
|
|
92
|
+
*
|
|
93
|
+
* @param uri - The matched URI
|
|
94
|
+
* @param variables - Extracted template variables
|
|
95
|
+
* @param ctx - Handler context
|
|
96
|
+
*/
|
|
97
|
+
type ResourceTemplateReadHandler = (uri: string, variables: Record<string, string>, ctx: HandlerContext) => Promise<Result<ResourceContent[], OutfitterError>>;
|
|
98
|
+
/**
|
|
99
|
+
* Definition of an MCP resource template with URI pattern matching.
|
|
100
|
+
*
|
|
101
|
+
* Templates use RFC 6570 Level 1 URI templates (e.g., `{param}`)
|
|
102
|
+
* to match and extract variables from URIs.
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* ```typescript
|
|
106
|
+
* const userTemplate: ResourceTemplateDefinition = {
|
|
107
|
+
* uriTemplate: "db:///users/{userId}/profile",
|
|
108
|
+
* name: "User Profile",
|
|
109
|
+
* handler: async (uri, variables) => {
|
|
110
|
+
* const profile = await getProfile(variables.userId);
|
|
111
|
+
* return Result.ok([{ uri, text: JSON.stringify(profile) }]);
|
|
112
|
+
* },
|
|
113
|
+
* };
|
|
114
|
+
* ```
|
|
115
|
+
*/
|
|
116
|
+
interface ResourceTemplateDefinition {
|
|
117
|
+
/** Optional completion handlers keyed by parameter name. */
|
|
118
|
+
complete?: Record<string, CompletionHandler>;
|
|
119
|
+
/** Optional description. */
|
|
120
|
+
description?: string;
|
|
121
|
+
/** Handler for reading matched resources. */
|
|
122
|
+
handler: ResourceTemplateReadHandler;
|
|
123
|
+
/** Optional MIME type. */
|
|
124
|
+
mimeType?: string;
|
|
125
|
+
/** Human-readable name for the template. */
|
|
126
|
+
name: string;
|
|
127
|
+
/** URI template with `{param}` placeholders (RFC 6570 Level 1). */
|
|
128
|
+
uriTemplate: string;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Handler for reading a typed resource template's content.
|
|
132
|
+
*
|
|
133
|
+
* @param uri - The matched URI
|
|
134
|
+
* @param params - Validated and parsed template parameters (typed via Zod schema)
|
|
135
|
+
* @param ctx - Handler context
|
|
136
|
+
*/
|
|
137
|
+
type TypedResourceTemplateReadHandler<TParams> = (uri: string, params: TParams, ctx: HandlerContext) => Promise<Result<ResourceContent[], OutfitterError>>;
|
|
138
|
+
/**
|
|
139
|
+
* Typed definition of an MCP resource template with Zod schema validation.
|
|
140
|
+
*
|
|
141
|
+
* Parallel to `ToolDefinition` — the `paramSchema` validates URI template
|
|
142
|
+
* variables before handler invocation, providing type-safe parameters
|
|
143
|
+
* and automatic coercion (e.g., string → number via `z.coerce.number()`).
|
|
144
|
+
*
|
|
145
|
+
* @typeParam TParams - The validated parameter type (inferred from Zod schema)
|
|
146
|
+
*
|
|
147
|
+
* @example
|
|
148
|
+
* ```typescript
|
|
149
|
+
* const userTemplate = defineResourceTemplate({
|
|
150
|
+
* uriTemplate: "db:///users/{userId}/posts/{postId}",
|
|
151
|
+
* name: "User Post",
|
|
152
|
+
* paramSchema: z.object({
|
|
153
|
+
* userId: z.string().min(1),
|
|
154
|
+
* postId: z.coerce.number().int().positive(),
|
|
155
|
+
* }),
|
|
156
|
+
* handler: async (uri, params, ctx) => {
|
|
157
|
+
* // params is { userId: string; postId: number } — validated and coerced
|
|
158
|
+
* const post = await getPost(params.userId, params.postId);
|
|
159
|
+
* return Result.ok([{ uri, text: JSON.stringify(post) }]);
|
|
160
|
+
* },
|
|
161
|
+
* });
|
|
162
|
+
* ```
|
|
163
|
+
*/
|
|
164
|
+
interface TypedResourceTemplateDefinition<TParams> {
|
|
165
|
+
/** Optional completion handlers keyed by parameter name. */
|
|
166
|
+
complete?: Record<string, CompletionHandler>;
|
|
167
|
+
/** Optional description. */
|
|
168
|
+
description?: string;
|
|
169
|
+
/**
|
|
170
|
+
* Handler for reading matched resources.
|
|
171
|
+
* Receives validated and coerced parameters (typed via `paramSchema`).
|
|
172
|
+
*/
|
|
173
|
+
handler: TypedResourceTemplateReadHandler<TParams>;
|
|
174
|
+
/** Optional MIME type. */
|
|
175
|
+
mimeType?: string;
|
|
176
|
+
/** Human-readable name for the template. */
|
|
177
|
+
name: string;
|
|
178
|
+
/**
|
|
179
|
+
* Zod schema for validating and parsing URI template parameters.
|
|
180
|
+
* Variables extracted from the URI template are validated against this schema
|
|
181
|
+
* before being passed to the handler. Supports coercion (e.g., `z.coerce.number()`).
|
|
182
|
+
*/
|
|
183
|
+
paramSchema: z.ZodType<TParams>;
|
|
184
|
+
/** URI template with `{param}` placeholders (RFC 6570 Level 1). */
|
|
185
|
+
uriTemplate: string;
|
|
186
|
+
}
|
|
187
|
+
export { TextResourceContent, BlobResourceContent, ResourceContent, ResourceReadHandler, ResourceDefinition, ResourceTemplateReadHandler, ResourceTemplateDefinition, TypedResourceTemplateReadHandler, TypedResourceTemplateDefinition };
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { ContentAnnotations } from "./mcp-q5hr7227.js";
|
|
2
|
+
import { OutfitterError, Result } from "@outfitter/contracts";
|
|
3
|
+
/**
|
|
4
|
+
* Result of a completion request.
|
|
5
|
+
*/
|
|
6
|
+
interface CompletionResult {
|
|
7
|
+
/** Whether there are more values */
|
|
8
|
+
hasMore?: boolean;
|
|
9
|
+
/** Total number of available values (for pagination) */
|
|
10
|
+
total?: number;
|
|
11
|
+
/** Completion values */
|
|
12
|
+
values: string[];
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Handler for generating completions.
|
|
16
|
+
*/
|
|
17
|
+
type CompletionHandler = (value: string) => Promise<CompletionResult>;
|
|
18
|
+
/**
|
|
19
|
+
* Reference to a prompt or resource for completion.
|
|
20
|
+
*/
|
|
21
|
+
type CompletionRef = {
|
|
22
|
+
type: "ref/prompt";
|
|
23
|
+
name: string;
|
|
24
|
+
} | {
|
|
25
|
+
type: "ref/resource";
|
|
26
|
+
uri: string;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Argument definition for a prompt.
|
|
30
|
+
*/
|
|
31
|
+
interface PromptArgument {
|
|
32
|
+
/** Optional completion handler for this argument */
|
|
33
|
+
complete?: CompletionHandler;
|
|
34
|
+
/** Human-readable description */
|
|
35
|
+
description?: string;
|
|
36
|
+
/** Argument name */
|
|
37
|
+
name: string;
|
|
38
|
+
/** Whether this argument is required */
|
|
39
|
+
required?: boolean;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Content block within a prompt message.
|
|
43
|
+
*/
|
|
44
|
+
interface PromptMessageContent {
|
|
45
|
+
/** Optional content annotations */
|
|
46
|
+
annotations?: ContentAnnotations;
|
|
47
|
+
/** Text content */
|
|
48
|
+
text: string;
|
|
49
|
+
/** Content type */
|
|
50
|
+
type: "text";
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* A message in a prompt response.
|
|
54
|
+
*/
|
|
55
|
+
interface PromptMessage {
|
|
56
|
+
/** Message content */
|
|
57
|
+
content: PromptMessageContent;
|
|
58
|
+
/** Message role */
|
|
59
|
+
role: "user" | "assistant";
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Result returned from getting a prompt.
|
|
63
|
+
*/
|
|
64
|
+
interface PromptResult {
|
|
65
|
+
/** Optional description override */
|
|
66
|
+
description?: string;
|
|
67
|
+
/** Prompt messages */
|
|
68
|
+
messages: PromptMessage[];
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Handler for generating prompt messages.
|
|
72
|
+
*/
|
|
73
|
+
type PromptHandler = (args: Record<string, string | undefined>) => Promise<Result<PromptResult, OutfitterError>>;
|
|
74
|
+
/**
|
|
75
|
+
* Definition of an MCP prompt.
|
|
76
|
+
*
|
|
77
|
+
* Prompts are reusable templates that generate messages for LLMs.
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* ```typescript
|
|
81
|
+
* const reviewPrompt: PromptDefinition = {
|
|
82
|
+
* name: "code-review",
|
|
83
|
+
* description: "Review code changes",
|
|
84
|
+
* arguments: [
|
|
85
|
+
* { name: "language", description: "Programming language", required: true },
|
|
86
|
+
* ],
|
|
87
|
+
* handler: async (args) => Result.ok({
|
|
88
|
+
* messages: [{ role: "user", content: { type: "text", text: `Review this ${args.language} code` } }],
|
|
89
|
+
* }),
|
|
90
|
+
* };
|
|
91
|
+
* ```
|
|
92
|
+
*/
|
|
93
|
+
interface PromptDefinition {
|
|
94
|
+
/** Prompt arguments */
|
|
95
|
+
arguments: PromptArgument[];
|
|
96
|
+
/** Human-readable description */
|
|
97
|
+
description?: string;
|
|
98
|
+
/** Handler to generate messages */
|
|
99
|
+
handler: PromptHandler;
|
|
100
|
+
/** Unique prompt name */
|
|
101
|
+
name: string;
|
|
102
|
+
}
|
|
103
|
+
export { CompletionResult, CompletionHandler, CompletionRef, PromptArgument, PromptMessageContent, PromptMessage, PromptResult, PromptHandler, PromptDefinition };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ToolDefinition } from "./mcp-
|
|
1
|
+
import { ToolDefinition } from "./mcp-knc1gq0g.js";
|
|
2
2
|
import { ActionRegistry, ActionSurface, AnyActionSpec } from "@outfitter/contracts";
|
|
3
3
|
interface BuildMcpToolsOptions {
|
|
4
4
|
readonly includeSurfaces?: readonly ActionSurface[];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { zodToJsonSchema } from "@outfitter/contracts/schema";
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { Handler, OutfitterError } from "@outfitter/contracts";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
/**
|
|
4
|
+
* Behavioral hints for MCP tools.
|
|
5
|
+
*
|
|
6
|
+
* Annotations help clients understand tool behavior without invoking them.
|
|
7
|
+
* All fields are optional — only include hints that apply.
|
|
8
|
+
*
|
|
9
|
+
* @see https://spec.modelcontextprotocol.io/specification/2025-03-26/server/tools/#annotations
|
|
10
|
+
*/
|
|
11
|
+
interface ToolAnnotations {
|
|
12
|
+
/** When true, the tool may perform destructive operations (e.g., deleting data). */
|
|
13
|
+
destructiveHint?: boolean;
|
|
14
|
+
/** When true, calling the tool multiple times with the same input has the same effect. */
|
|
15
|
+
idempotentHint?: boolean;
|
|
16
|
+
/** When true, the tool may interact with external systems beyond the server. */
|
|
17
|
+
openWorldHint?: boolean;
|
|
18
|
+
/** When true, the tool does not modify any state. */
|
|
19
|
+
readOnlyHint?: boolean;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Common annotation presets for MCP tools.
|
|
23
|
+
*
|
|
24
|
+
* Use these as a starting point and spread-override individual hints:
|
|
25
|
+
*
|
|
26
|
+
* ```typescript
|
|
27
|
+
* annotations: { ...TOOL_ANNOTATIONS.readOnly, openWorldHint: true }
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* For multi-action tools (e.g., a single tool with read and write actions),
|
|
31
|
+
* use the most conservative union of hints — if any action is destructive,
|
|
32
|
+
* mark the whole tool as destructive. Per-action annotations are an MCP spec
|
|
33
|
+
* limitation; presets + spread cover most edge cases.
|
|
34
|
+
*/
|
|
35
|
+
declare const TOOL_ANNOTATIONS: {
|
|
36
|
+
readonly destructive: ToolAnnotations;
|
|
37
|
+
readonly openWorld: ToolAnnotations;
|
|
38
|
+
readonly readOnly: ToolAnnotations;
|
|
39
|
+
readonly write: ToolAnnotations;
|
|
40
|
+
readonly writeIdempotent: ToolAnnotations;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Definition of an MCP tool that can be invoked by clients.
|
|
44
|
+
*
|
|
45
|
+
* Tools are the primary way clients interact with MCP servers.
|
|
46
|
+
* Each tool has a name, description, input schema (for validation),
|
|
47
|
+
* and a handler function that processes requests.
|
|
48
|
+
*
|
|
49
|
+
* @typeParam TInput - The validated input type (inferred from Zod schema)
|
|
50
|
+
* @typeParam TOutput - The success output type
|
|
51
|
+
* @typeParam TError - The error type (must extend OutfitterError)
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```typescript
|
|
55
|
+
* const getUserTool: ToolDefinition<
|
|
56
|
+
* { userId: string },
|
|
57
|
+
* { name: string; email: string },
|
|
58
|
+
* NotFoundError
|
|
59
|
+
* > = {
|
|
60
|
+
* name: "get-user",
|
|
61
|
+
* description: "Retrieve a user by ID",
|
|
62
|
+
* inputSchema: z.object({ userId: z.string().uuid() }),
|
|
63
|
+
* handler: async (input, ctx) => {
|
|
64
|
+
* ctx.logger.debug("Fetching user", { userId: input.userId });
|
|
65
|
+
* const user = await db.users.find(input.userId);
|
|
66
|
+
* if (!user) {
|
|
67
|
+
* return Result.err(new NotFoundError({
|
|
68
|
+
* message: `User ${input.userId} not found`,
|
|
69
|
+
* resourceType: "user",
|
|
70
|
+
* resourceId: input.userId,
|
|
71
|
+
* }));
|
|
72
|
+
* }
|
|
73
|
+
* return Result.ok({ name: user.name, email: user.email });
|
|
74
|
+
* },
|
|
75
|
+
* };
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
78
|
+
interface ToolDefinition<
|
|
79
|
+
TInput,
|
|
80
|
+
TOutput,
|
|
81
|
+
TError extends OutfitterError = OutfitterError
|
|
82
|
+
> {
|
|
83
|
+
/**
|
|
84
|
+
* Optional behavioral annotations for the tool.
|
|
85
|
+
* Helps clients understand tool behavior without invoking it.
|
|
86
|
+
*/
|
|
87
|
+
annotations?: ToolAnnotations;
|
|
88
|
+
/**
|
|
89
|
+
* Whether the tool should be deferred for tool search.
|
|
90
|
+
* Defaults to true for domain tools; core tools set this to false.
|
|
91
|
+
*/
|
|
92
|
+
deferLoading?: boolean;
|
|
93
|
+
/**
|
|
94
|
+
* Human-readable description of what the tool does.
|
|
95
|
+
* Shown to clients and used by LLMs to understand tool capabilities.
|
|
96
|
+
*/
|
|
97
|
+
description: string;
|
|
98
|
+
/**
|
|
99
|
+
* Handler function that processes the tool invocation.
|
|
100
|
+
* Receives validated input and HandlerContext, returns Result.
|
|
101
|
+
*/
|
|
102
|
+
handler: Handler<TInput, TOutput, TError>;
|
|
103
|
+
/**
|
|
104
|
+
* Zod schema for validating and parsing input.
|
|
105
|
+
* The schema defines the expected input structure.
|
|
106
|
+
*/
|
|
107
|
+
inputSchema: z.ZodType<TInput>;
|
|
108
|
+
/**
|
|
109
|
+
* Unique tool name (kebab-case recommended).
|
|
110
|
+
* Used by clients to invoke the tool.
|
|
111
|
+
*/
|
|
112
|
+
name: string;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Serialized tool information for MCP protocol.
|
|
116
|
+
* This is the format sent to clients during tool listing.
|
|
117
|
+
*/
|
|
118
|
+
interface SerializedTool {
|
|
119
|
+
/** Behavioral annotations for the tool */
|
|
120
|
+
annotations?: ToolAnnotations;
|
|
121
|
+
/** MCP tool-search hint: whether tool is deferred */
|
|
122
|
+
defer_loading?: boolean;
|
|
123
|
+
/** Tool description */
|
|
124
|
+
description: string;
|
|
125
|
+
/** JSON Schema representation of the input schema */
|
|
126
|
+
inputSchema: Record<string, unknown>;
|
|
127
|
+
/** Tool name */
|
|
128
|
+
name: string;
|
|
129
|
+
}
|
|
130
|
+
export { ToolAnnotations, TOOL_ANNOTATIONS, ToolDefinition, SerializedTool };
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// packages/mcp/src/internal/log-config.ts
|
|
3
|
+
import { getEnvironment, getEnvironmentDefaults } from "@outfitter/config";
|
|
4
|
+
import { createPrettyFormatter } from "@outfitter/logging";
|
|
5
|
+
var VALID_MCP_LOG_LEVELS = new Set([
|
|
6
|
+
"debug",
|
|
7
|
+
"info",
|
|
8
|
+
"notice",
|
|
9
|
+
"warning",
|
|
10
|
+
"error",
|
|
11
|
+
"critical",
|
|
12
|
+
"alert",
|
|
13
|
+
"emergency"
|
|
14
|
+
]);
|
|
15
|
+
var DEFAULTS_TO_MCP = {
|
|
16
|
+
debug: "debug",
|
|
17
|
+
info: "info",
|
|
18
|
+
warn: "warning",
|
|
19
|
+
error: "error"
|
|
20
|
+
};
|
|
21
|
+
function createDefaultMcpSink() {
|
|
22
|
+
const formatter = createPrettyFormatter({ colors: false });
|
|
23
|
+
return {
|
|
24
|
+
formatter,
|
|
25
|
+
write(record, formatted) {
|
|
26
|
+
const serialized = formatted ?? formatter.format(record);
|
|
27
|
+
const line = serialized.endsWith(`
|
|
28
|
+
`) ? serialized : `${serialized}
|
|
29
|
+
`;
|
|
30
|
+
if (typeof process !== "undefined" && process.stderr?.write) {
|
|
31
|
+
process.stderr.write(line);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
function resolveDefaultLogLevel(options) {
|
|
37
|
+
const envLogLevel = process.env["OUTFITTER_LOG_LEVEL"];
|
|
38
|
+
if (envLogLevel !== undefined && VALID_MCP_LOG_LEVELS.has(envLogLevel)) {
|
|
39
|
+
return envLogLevel;
|
|
40
|
+
}
|
|
41
|
+
if (options.defaultLogLevel !== undefined && (options.defaultLogLevel === null || VALID_MCP_LOG_LEVELS.has(options.defaultLogLevel))) {
|
|
42
|
+
return options.defaultLogLevel;
|
|
43
|
+
}
|
|
44
|
+
const env = getEnvironment();
|
|
45
|
+
const defaults = getEnvironmentDefaults(env);
|
|
46
|
+
if (defaults.logLevel !== null) {
|
|
47
|
+
const mapped = DEFAULTS_TO_MCP[defaults.logLevel];
|
|
48
|
+
if (mapped !== undefined) {
|
|
49
|
+
return mapped;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export { VALID_MCP_LOG_LEVELS, DEFAULTS_TO_MCP, createDefaultMcpSink, resolveDefaultLogLevel };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared content type definitions used across prompt and resource types.
|
|
3
|
+
*
|
|
4
|
+
* @internal
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Annotations for content items (resource content, prompt messages).
|
|
8
|
+
*
|
|
9
|
+
* Provides hints about content audience and priority.
|
|
10
|
+
*
|
|
11
|
+
* @see https://spec.modelcontextprotocol.io/specification/2025-03-26/server/utilities/annotations/
|
|
12
|
+
*/
|
|
13
|
+
interface ContentAnnotations {
|
|
14
|
+
/**
|
|
15
|
+
* Who the content is intended for.
|
|
16
|
+
* Can include "user", "assistant", or both.
|
|
17
|
+
*/
|
|
18
|
+
audience?: Array<"user" | "assistant">;
|
|
19
|
+
/**
|
|
20
|
+
* Priority level from 0.0 (least) to 1.0 (most important).
|
|
21
|
+
*/
|
|
22
|
+
priority?: number;
|
|
23
|
+
}
|
|
24
|
+
export { ContentAnnotations };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// packages/mcp/src/progress.ts
|
|
3
|
+
function mapStreamEventToNotification(token, event, latestProgress) {
|
|
4
|
+
switch (event.type) {
|
|
5
|
+
case "start": {
|
|
6
|
+
return {
|
|
7
|
+
method: "notifications/progress",
|
|
8
|
+
params: {
|
|
9
|
+
progressToken: token,
|
|
10
|
+
progress: latestProgress,
|
|
11
|
+
message: `[start] ${event.command}`
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
case "step": {
|
|
16
|
+
const durationSuffix = event.duration_ms !== undefined ? ` (${event.duration_ms}ms)` : "";
|
|
17
|
+
return {
|
|
18
|
+
method: "notifications/progress",
|
|
19
|
+
params: {
|
|
20
|
+
progressToken: token,
|
|
21
|
+
progress: latestProgress,
|
|
22
|
+
message: `[step] ${event.name}: ${event.status}${durationSuffix}`
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
case "progress": {
|
|
27
|
+
const params = {
|
|
28
|
+
progressToken: token,
|
|
29
|
+
progress: event.current,
|
|
30
|
+
total: event.total
|
|
31
|
+
};
|
|
32
|
+
if (event.message !== undefined) {
|
|
33
|
+
params.message = event.message;
|
|
34
|
+
}
|
|
35
|
+
return {
|
|
36
|
+
method: "notifications/progress",
|
|
37
|
+
params
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function createMcpProgressCallback(progressToken, send) {
|
|
43
|
+
let latestProgress = 0;
|
|
44
|
+
return (event) => {
|
|
45
|
+
if (event.type === "progress") {
|
|
46
|
+
latestProgress = event.current;
|
|
47
|
+
}
|
|
48
|
+
const notification = mapStreamEventToNotification(progressToken, event, latestProgress);
|
|
49
|
+
send(notification);
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export { createMcpProgressCallback };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { ProgressCallback } from "@outfitter/contracts/stream";
|
|
2
|
+
/**
|
|
3
|
+
* Function signature for sending a raw MCP notification.
|
|
4
|
+
*
|
|
5
|
+
* Matches the `sdkServer.notification()` method shape from the MCP SDK.
|
|
6
|
+
*/
|
|
7
|
+
type McpNotificationSender = (notification: unknown) => void;
|
|
8
|
+
/**
|
|
9
|
+
* MCP progress notification payload matching the MCP specification.
|
|
10
|
+
*
|
|
11
|
+
* @see https://spec.modelcontextprotocol.io/specification/2025-03-26/server/utilities/progress/
|
|
12
|
+
*/
|
|
13
|
+
interface McpProgressNotification {
|
|
14
|
+
method: "notifications/progress";
|
|
15
|
+
params: {
|
|
16
|
+
progressToken: string | number;
|
|
17
|
+
progress: number;
|
|
18
|
+
total?: number;
|
|
19
|
+
message?: string;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Create a {@link ProgressCallback} that emits MCP `notifications/progress`.
|
|
24
|
+
*
|
|
25
|
+
* Each call to the returned callback translates a {@link StreamEvent} into
|
|
26
|
+
* an MCP progress notification and sends it via the provided sender function.
|
|
27
|
+
*
|
|
28
|
+
* @param progressToken - The progress token from the MCP client request
|
|
29
|
+
* @param send - Function to send the raw MCP notification (typically `sdkServer.notification`)
|
|
30
|
+
* @returns A `ProgressCallback` compatible with `ctx.progress`
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```typescript
|
|
34
|
+
* const progress = createMcpProgressCallback(
|
|
35
|
+
* "tok-123",
|
|
36
|
+
* (n) => sdkServer.notification(n)
|
|
37
|
+
* );
|
|
38
|
+
*
|
|
39
|
+
* // In handler:
|
|
40
|
+
* ctx.progress?.({ type: "start", command: "deploy", ts: new Date().toISOString() });
|
|
41
|
+
* ctx.progress?.({ type: "progress", current: 5, total: 10 });
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
declare function createMcpProgressCallback(progressToken: string | number, send: McpNotificationSender): ProgressCallback;
|
|
45
|
+
export { McpNotificationSender, McpProgressNotification, createMcpProgressCallback };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { McpServer } from "./mcp-
|
|
1
|
+
import { McpServer } from "./mcp-7btcghjj.js";
|
|
2
2
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
3
3
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
4
|
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|