@phake/mcp 0.0.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/LICENSE +21 -0
- package/README.md +187 -0
- package/dist/adapters/http-node/http/app.d.ts +5 -0
- package/dist/adapters/http-node/http/auth-app.d.ts +5 -0
- package/dist/adapters/http-node/http/middlewares/auth.d.ts +39 -0
- package/dist/adapters/http-node/http/middlewares/cors.d.ts +8 -0
- package/dist/adapters/http-node/http/routes/health.d.ts +5 -0
- package/dist/adapters/http-node/http/routes/mcp.d.ts +11 -0
- package/dist/adapters/http-node/middleware.security.d.ts +6 -0
- package/dist/adapters/http-node/routes.discovery.d.ts +6 -0
- package/dist/adapters/http-node/routes.oauth.d.ts +7 -0
- package/dist/adapters/http-worker/index.d.ts +48 -0
- package/dist/adapters/http-worker/mcp.handler.d.ts +24 -0
- package/dist/adapters/http-worker/routes.discovery.d.ts +7 -0
- package/dist/adapters/http-worker/routes.oauth.d.ts +8 -0
- package/dist/adapters/http-worker/security.d.ts +7 -0
- package/dist/index-1zyem3xr.js +14893 -0
- package/dist/index-4f4xvtt9.js +19552 -0
- package/dist/index-sbqy8kgq.js +3478 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +1083 -0
- package/dist/mcp-server.d.ts +18 -0
- package/dist/runtime/node/capabilities.d.ts +2 -0
- package/dist/runtime/node/context.d.ts +29 -0
- package/dist/runtime/node/index.d.ts +5 -0
- package/dist/runtime/node/index.js +27 -0
- package/dist/runtime/node/mcp.d.ts +28 -0
- package/dist/runtime/node/storage/file.d.ts +44 -0
- package/dist/runtime/node/storage/sqlite.d.ts +213 -0
- package/dist/runtime/worker/index.d.ts +1 -0
- package/dist/runtime/worker/index.js +12 -0
- package/dist/shared/auth/index.d.ts +1 -0
- package/dist/shared/auth/strategy.d.ts +71 -0
- package/dist/shared/config/env.d.ts +52 -0
- package/dist/shared/config/index.d.ts +2 -0
- package/dist/shared/config/metadata.d.ts +5 -0
- package/dist/shared/crypto/aes-gcm.d.ts +37 -0
- package/dist/shared/crypto/index.d.ts +1 -0
- package/dist/shared/http/cors.d.ts +20 -0
- package/dist/shared/http/index.d.ts +2 -0
- package/dist/shared/http/response.d.ts +52 -0
- package/dist/shared/mcp/dispatcher.d.ts +81 -0
- package/dist/shared/mcp/index.d.ts +3 -0
- package/dist/shared/mcp/security.d.ts +23 -0
- package/dist/shared/mcp/server-internals.d.ts +79 -0
- package/dist/shared/oauth/cimd.d.ts +43 -0
- package/dist/shared/oauth/discovery-handlers.d.ts +14 -0
- package/dist/shared/oauth/discovery.d.ts +26 -0
- package/dist/shared/oauth/endpoints.d.ts +11 -0
- package/dist/shared/oauth/flow.d.ts +31 -0
- package/dist/shared/oauth/index.d.ts +9 -0
- package/dist/shared/oauth/input-parsers.d.ts +43 -0
- package/dist/shared/oauth/refresh.d.ts +61 -0
- package/dist/shared/oauth/ssrf.d.ts +31 -0
- package/dist/shared/oauth/types.d.ts +78 -0
- package/dist/shared/schemas/prompts.d.ts +1 -0
- package/dist/shared/services/http-client.d.ts +16 -0
- package/dist/shared/services/index.d.ts +1 -0
- package/dist/shared/storage/index.d.ts +4 -0
- package/dist/shared/storage/interface.d.ts +99 -0
- package/dist/shared/storage/kv.d.ts +68 -0
- package/dist/shared/storage/memory.d.ts +91 -0
- package/dist/shared/storage/singleton.d.ts +4 -0
- package/dist/shared/tools/echo.d.ts +16 -0
- package/dist/shared/tools/health.d.ts +13 -0
- package/dist/shared/tools/index.d.ts +4 -0
- package/dist/shared/tools/registry.d.ts +64 -0
- package/dist/shared/tools/types.d.ts +161 -0
- package/dist/shared/types/auth.d.ts +35 -0
- package/dist/shared/types/context.d.ts +79 -0
- package/dist/shared/types/index.d.ts +8 -0
- package/dist/shared/types/provider.d.ts +28 -0
- package/dist/shared/utils/base64.d.ts +12 -0
- package/dist/shared/utils/cancellation.d.ts +13 -0
- package/dist/shared/utils/elicitation.d.ts +247 -0
- package/dist/shared/utils/formatting.d.ts +106 -0
- package/dist/shared/utils/index.d.ts +11 -0
- package/dist/shared/utils/limits.d.ts +6 -0
- package/dist/shared/utils/logger.d.ts +20 -0
- package/dist/shared/utils/pagination.d.ts +11 -0
- package/dist/shared/utils/progress.d.ts +56 -0
- package/dist/shared/utils/roots.d.ts +62 -0
- package/dist/shared/utils/sampling.d.ts +155 -0
- package/dist/shared/utils/security.d.ts +6 -0
- package/package.json +55 -0
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Elicitation utilities for servers to request user input from clients.
|
|
3
|
+
*
|
|
4
|
+
* ⚠️ NODE.JS ONLY - These utilities require SDK bidirectional support
|
|
5
|
+
* (server.request()) which is not available in the Cloudflare Workers runtime.
|
|
6
|
+
* The Workers dispatcher does not support server→client requests.
|
|
7
|
+
*
|
|
8
|
+
* Two modes:
|
|
9
|
+
* - Form: Structured input via a schema (text fields, checkboxes, dropdowns)
|
|
10
|
+
* - URL: Redirect user to external URL for out-of-band interaction
|
|
11
|
+
*
|
|
12
|
+
* Per MCP spec:
|
|
13
|
+
* - Elicitation is a CLIENT capability
|
|
14
|
+
* - Servers send elicitation/create requests TO clients
|
|
15
|
+
* - Clients display the form/URL and return user response
|
|
16
|
+
*/
|
|
17
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
18
|
+
import { z } from "zod";
|
|
19
|
+
/** Boolean field schema */
|
|
20
|
+
export interface BooleanFieldSchema {
|
|
21
|
+
type: "boolean";
|
|
22
|
+
title?: string;
|
|
23
|
+
description?: string;
|
|
24
|
+
default?: boolean;
|
|
25
|
+
}
|
|
26
|
+
/** String field schema */
|
|
27
|
+
export interface StringFieldSchema {
|
|
28
|
+
type: "string";
|
|
29
|
+
title?: string;
|
|
30
|
+
description?: string;
|
|
31
|
+
minLength?: number;
|
|
32
|
+
maxLength?: number;
|
|
33
|
+
format?: "email" | "uri" | "date" | "date-time";
|
|
34
|
+
default?: string;
|
|
35
|
+
}
|
|
36
|
+
/** Number field schema */
|
|
37
|
+
export interface NumberFieldSchema {
|
|
38
|
+
type: "number" | "integer";
|
|
39
|
+
title?: string;
|
|
40
|
+
description?: string;
|
|
41
|
+
minimum?: number;
|
|
42
|
+
maximum?: number;
|
|
43
|
+
default?: number;
|
|
44
|
+
}
|
|
45
|
+
/** Single-select enum with titles (preferred) */
|
|
46
|
+
export interface TitledEnumFieldSchema {
|
|
47
|
+
type: "string";
|
|
48
|
+
title?: string;
|
|
49
|
+
description?: string;
|
|
50
|
+
oneOf: Array<{
|
|
51
|
+
const: string;
|
|
52
|
+
title: string;
|
|
53
|
+
}>;
|
|
54
|
+
default?: string;
|
|
55
|
+
}
|
|
56
|
+
/** Single-select enum without titles */
|
|
57
|
+
export interface UntitledEnumFieldSchema {
|
|
58
|
+
type: "string";
|
|
59
|
+
title?: string;
|
|
60
|
+
description?: string;
|
|
61
|
+
enum: string[];
|
|
62
|
+
default?: string;
|
|
63
|
+
}
|
|
64
|
+
/** Multi-select enum */
|
|
65
|
+
export interface MultiSelectFieldSchema {
|
|
66
|
+
type: "array";
|
|
67
|
+
title?: string;
|
|
68
|
+
description?: string;
|
|
69
|
+
minItems?: number;
|
|
70
|
+
maxItems?: number;
|
|
71
|
+
items: {
|
|
72
|
+
type: "string";
|
|
73
|
+
enum: string[];
|
|
74
|
+
} | {
|
|
75
|
+
anyOf: Array<{
|
|
76
|
+
const: string;
|
|
77
|
+
title: string;
|
|
78
|
+
}>;
|
|
79
|
+
};
|
|
80
|
+
default?: string[];
|
|
81
|
+
}
|
|
82
|
+
/** All supported field schema types */
|
|
83
|
+
export type FieldSchema = BooleanFieldSchema | StringFieldSchema | NumberFieldSchema | TitledEnumFieldSchema | UntitledEnumFieldSchema | MultiSelectFieldSchema;
|
|
84
|
+
/** Schema for form elicitation (flat object with primitive fields only) */
|
|
85
|
+
export interface ElicitationSchema {
|
|
86
|
+
type: "object";
|
|
87
|
+
properties: Record<string, FieldSchema>;
|
|
88
|
+
required?: string[];
|
|
89
|
+
}
|
|
90
|
+
/** Form elicitation request */
|
|
91
|
+
export interface FormElicitationRequest {
|
|
92
|
+
mode?: "form";
|
|
93
|
+
message: string;
|
|
94
|
+
requestedSchema: ElicitationSchema;
|
|
95
|
+
}
|
|
96
|
+
/** URL elicitation request */
|
|
97
|
+
export interface UrlElicitationRequest {
|
|
98
|
+
mode: "url";
|
|
99
|
+
message: string;
|
|
100
|
+
elicitationId: string;
|
|
101
|
+
url: string;
|
|
102
|
+
}
|
|
103
|
+
export type ElicitationRequest = FormElicitationRequest | UrlElicitationRequest;
|
|
104
|
+
/** User's response to elicitation */
|
|
105
|
+
export interface ElicitResult {
|
|
106
|
+
action: "accept" | "decline" | "cancel";
|
|
107
|
+
content?: Record<string, string | number | boolean | string[]>;
|
|
108
|
+
}
|
|
109
|
+
export declare const ElicitResultSchema: z.ZodObject<{
|
|
110
|
+
action: z.ZodEnum<{
|
|
111
|
+
cancel: "cancel";
|
|
112
|
+
accept: "accept";
|
|
113
|
+
decline: "decline";
|
|
114
|
+
}>;
|
|
115
|
+
content: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodArray<z.ZodString>]>>>;
|
|
116
|
+
}, z.core.$strip>;
|
|
117
|
+
/**
|
|
118
|
+
* Validate that elicitation schema is flat (no nested objects/arrays of objects).
|
|
119
|
+
* Per MCP spec: requestedSchema must have type: 'object' at root with only
|
|
120
|
+
* primitive properties (no nesting).
|
|
121
|
+
*
|
|
122
|
+
* @throws Error if schema contains nested objects or invalid structure
|
|
123
|
+
*/
|
|
124
|
+
export declare function validateElicitationSchema(schema: ElicitationSchema): void;
|
|
125
|
+
/**
|
|
126
|
+
* Check if client supports form elicitation.
|
|
127
|
+
*/
|
|
128
|
+
export declare function clientSupportsFormElicitation(server: McpServer): boolean;
|
|
129
|
+
/**
|
|
130
|
+
* Check if client supports URL elicitation.
|
|
131
|
+
*/
|
|
132
|
+
export declare function clientSupportsUrlElicitation(server: McpServer): boolean;
|
|
133
|
+
/**
|
|
134
|
+
* Request user input via form elicitation.
|
|
135
|
+
*
|
|
136
|
+
* @example
|
|
137
|
+
* ```typescript
|
|
138
|
+
* const result = await elicitForm(server, {
|
|
139
|
+
* message: 'Configure your preferences:',
|
|
140
|
+
* requestedSchema: {
|
|
141
|
+
* type: 'object',
|
|
142
|
+
* properties: {
|
|
143
|
+
* apiKey: { type: 'string', title: 'API Key' },
|
|
144
|
+
* enabled: { type: 'boolean', title: 'Enable feature', default: true },
|
|
145
|
+
* theme: {
|
|
146
|
+
* type: 'string',
|
|
147
|
+
* title: 'Theme',
|
|
148
|
+
* oneOf: [
|
|
149
|
+
* { const: 'light', title: 'Light' },
|
|
150
|
+
* { const: 'dark', title: 'Dark' }
|
|
151
|
+
* ]
|
|
152
|
+
* }
|
|
153
|
+
* },
|
|
154
|
+
* required: ['apiKey']
|
|
155
|
+
* }
|
|
156
|
+
* });
|
|
157
|
+
*
|
|
158
|
+
* if (result.action === 'accept') {
|
|
159
|
+
* console.log('API Key:', result.content?.apiKey);
|
|
160
|
+
* }
|
|
161
|
+
* ```
|
|
162
|
+
*/
|
|
163
|
+
export declare function elicitForm(server: McpServer, request: FormElicitationRequest): Promise<ElicitResult>;
|
|
164
|
+
/**
|
|
165
|
+
* Request user interaction via URL elicitation.
|
|
166
|
+
*
|
|
167
|
+
* @example
|
|
168
|
+
* ```typescript
|
|
169
|
+
* const elicitationId = crypto.randomUUID();
|
|
170
|
+
*
|
|
171
|
+
* const result = await elicitUrl(server, {
|
|
172
|
+
* message: 'Please complete authentication:',
|
|
173
|
+
* elicitationId,
|
|
174
|
+
* url: 'https://auth.example.com/oauth/authorize?state=xyz'
|
|
175
|
+
* });
|
|
176
|
+
*
|
|
177
|
+
* // After external callback completes:
|
|
178
|
+
* await notifyElicitationComplete(server, elicitationId);
|
|
179
|
+
* ```
|
|
180
|
+
*/
|
|
181
|
+
export declare function elicitUrl(server: McpServer, request: Omit<UrlElicitationRequest, "mode">): Promise<ElicitResult>;
|
|
182
|
+
/**
|
|
183
|
+
* Notify client that URL elicitation has completed (external flow finished).
|
|
184
|
+
*/
|
|
185
|
+
export declare function notifyElicitationComplete(server: McpServer, elicitationId: string): Promise<void>;
|
|
186
|
+
/**
|
|
187
|
+
* Request a simple confirmation from the user.
|
|
188
|
+
*
|
|
189
|
+
* @example
|
|
190
|
+
* ```typescript
|
|
191
|
+
* const confirmed = await confirm(server, 'Delete all items?');
|
|
192
|
+
* if (confirmed) {
|
|
193
|
+
* // proceed with deletion
|
|
194
|
+
* }
|
|
195
|
+
* ```
|
|
196
|
+
*/
|
|
197
|
+
export declare function confirm(server: McpServer, message: string, options?: {
|
|
198
|
+
confirmLabel?: string;
|
|
199
|
+
declineLabel?: string;
|
|
200
|
+
}): Promise<boolean>;
|
|
201
|
+
/**
|
|
202
|
+
* Request a single text input from the user.
|
|
203
|
+
*
|
|
204
|
+
* @example
|
|
205
|
+
* ```typescript
|
|
206
|
+
* const apiKey = await promptText(server, 'Enter your API key:', {
|
|
207
|
+
* title: 'API Key',
|
|
208
|
+
* required: true
|
|
209
|
+
* });
|
|
210
|
+
*
|
|
211
|
+
* if (apiKey) {
|
|
212
|
+
* // use the API key
|
|
213
|
+
* }
|
|
214
|
+
* ```
|
|
215
|
+
*/
|
|
216
|
+
export declare function promptText(server: McpServer, message: string, options?: {
|
|
217
|
+
title?: string;
|
|
218
|
+
description?: string;
|
|
219
|
+
defaultValue?: string;
|
|
220
|
+
required?: boolean;
|
|
221
|
+
minLength?: number;
|
|
222
|
+
maxLength?: number;
|
|
223
|
+
}): Promise<string | undefined>;
|
|
224
|
+
/**
|
|
225
|
+
* Request a selection from a list of options.
|
|
226
|
+
*
|
|
227
|
+
* @example
|
|
228
|
+
* ```typescript
|
|
229
|
+
* const choice = await promptSelect(server, 'Choose a model:', [
|
|
230
|
+
* { value: 'gpt-4', label: 'GPT-4 (Best quality)' },
|
|
231
|
+
* { value: 'gpt-3.5', label: 'GPT-3.5 (Faster)' },
|
|
232
|
+
* { value: 'claude', label: 'Claude (Alternative)' }
|
|
233
|
+
* ]);
|
|
234
|
+
*
|
|
235
|
+
* if (choice) {
|
|
236
|
+
* console.log('Selected:', choice);
|
|
237
|
+
* }
|
|
238
|
+
* ```
|
|
239
|
+
*/
|
|
240
|
+
export declare function promptSelect(server: McpServer, message: string, options: Array<{
|
|
241
|
+
value: string;
|
|
242
|
+
label: string;
|
|
243
|
+
}>, config?: {
|
|
244
|
+
title?: string;
|
|
245
|
+
defaultValue?: string;
|
|
246
|
+
required?: boolean;
|
|
247
|
+
}): Promise<string | undefined>;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Message formatting utilities for consistent, LLM-friendly output.
|
|
3
|
+
*
|
|
4
|
+
* These utilities help create clear, scannable responses that are optimized
|
|
5
|
+
* for both LLM understanding and human readability.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Summarize a list of items with preview and details sections.
|
|
9
|
+
*
|
|
10
|
+
* @param items - Array of items to summarize
|
|
11
|
+
* @param formatPreview - Function to format a single-line preview of each item
|
|
12
|
+
* @param options - Formatting options
|
|
13
|
+
* @returns Formatted summary with preview list and optional details
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* const users = [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }];
|
|
17
|
+
* const summary = summarizeList(users, (u) => `${u.id}. ${u.name}`);
|
|
18
|
+
* // Returns:
|
|
19
|
+
* // ## List (2 items)
|
|
20
|
+
* // 1. Alice
|
|
21
|
+
* // 2. Bob
|
|
22
|
+
*/
|
|
23
|
+
export declare function summarizeList<T>(items: T[], formatPreview: (item: T) => string, options?: {
|
|
24
|
+
title?: string;
|
|
25
|
+
maxPreview?: number;
|
|
26
|
+
detailsFormatter?: (item: T) => string;
|
|
27
|
+
maxDetails?: number;
|
|
28
|
+
}): string;
|
|
29
|
+
/**
|
|
30
|
+
* Summarize the results of a batch operation.
|
|
31
|
+
*
|
|
32
|
+
* @param results - Array of operation results
|
|
33
|
+
* @param options - Formatting options
|
|
34
|
+
* @returns Formatted batch summary with success/failure counts
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* const results = [
|
|
38
|
+
* { success: true, id: '1', message: 'Created user Alice' },
|
|
39
|
+
* { success: false, id: '2', message: 'User Bob already exists' },
|
|
40
|
+
* ];
|
|
41
|
+
* const summary = summarizeBatch(results, {
|
|
42
|
+
* operationName: 'Create Users',
|
|
43
|
+
* successFormatter: (r) => `✓ ${r.message}`,
|
|
44
|
+
* errorFormatter: (r) => `✗ ${r.message}`,
|
|
45
|
+
* });
|
|
46
|
+
*/
|
|
47
|
+
export declare function summarizeBatch<T extends {
|
|
48
|
+
success: boolean;
|
|
49
|
+
}>(results: T[], options: {
|
|
50
|
+
operationName: string;
|
|
51
|
+
successFormatter: (result: T) => string;
|
|
52
|
+
errorFormatter: (result: T) => string;
|
|
53
|
+
}): string;
|
|
54
|
+
/**
|
|
55
|
+
* Format a field change for before/after comparison.
|
|
56
|
+
*
|
|
57
|
+
* @param fieldName - Human-readable field name
|
|
58
|
+
* @param before - Value before change
|
|
59
|
+
* @param after - Value after change
|
|
60
|
+
* @returns Formatted change description
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* formatFieldChange('Status', 'pending', 'completed')
|
|
64
|
+
* // Returns: "Status: pending → completed"
|
|
65
|
+
*/
|
|
66
|
+
export declare function formatFieldChange(fieldName: string, before: string | number | boolean | null | undefined, after: string | number | boolean | null | undefined): string;
|
|
67
|
+
/**
|
|
68
|
+
* Create a structured markdown section with optional tags.
|
|
69
|
+
*
|
|
70
|
+
* @param content - Content to wrap
|
|
71
|
+
* @param options - Section options
|
|
72
|
+
* @returns Formatted section with tags
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* createSection('User details: Alice', { tag: 'user_info' })
|
|
76
|
+
* // Returns:
|
|
77
|
+
* // <ove tag="user_info">
|
|
78
|
+
* // User details: Alice
|
|
79
|
+
* // </ove>
|
|
80
|
+
*/
|
|
81
|
+
export declare function createSection(content: string, options?: {
|
|
82
|
+
tag?: string;
|
|
83
|
+
indent?: number;
|
|
84
|
+
}): string;
|
|
85
|
+
/**
|
|
86
|
+
* Truncate text to a maximum length with ellipsis.
|
|
87
|
+
*
|
|
88
|
+
* @param text - Text to truncate
|
|
89
|
+
* @param maxLength - Maximum length (default: 100)
|
|
90
|
+
* @returns Truncated text
|
|
91
|
+
*/
|
|
92
|
+
export declare function truncate(text: string, maxLength?: number): string;
|
|
93
|
+
/**
|
|
94
|
+
* Format a list of key-value pairs as markdown.
|
|
95
|
+
*
|
|
96
|
+
* @param pairs - Object with key-value pairs
|
|
97
|
+
* @returns Formatted markdown list
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* formatKeyValueList({ name: 'Alice', age: 30, role: 'Admin' })
|
|
101
|
+
* // Returns:
|
|
102
|
+
* // - **Name**: Alice
|
|
103
|
+
* // - **Age**: 30
|
|
104
|
+
* // - **Role**: Admin
|
|
105
|
+
*/
|
|
106
|
+
export declare function formatKeyValueList(pairs: Record<string, string | number | boolean | null | undefined>): string;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export * from "./base64.js";
|
|
2
|
+
export * from "./cancellation.js";
|
|
3
|
+
export * from "./elicitation.js";
|
|
4
|
+
export * from "./formatting.js";
|
|
5
|
+
export * from "./limits.js";
|
|
6
|
+
export * from "./logger.js";
|
|
7
|
+
export * from "./pagination.js";
|
|
8
|
+
export * from "./progress.js";
|
|
9
|
+
export * from "./roots.js";
|
|
10
|
+
export * from "./sampling.js";
|
|
11
|
+
export * from "./security.js";
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export type TokenBucket = {
|
|
2
|
+
take: (n?: number) => boolean;
|
|
3
|
+
refill: (tokens?: number) => void;
|
|
4
|
+
};
|
|
5
|
+
export declare const makeTokenBucket: (capacity: number, refillPerSec: number) => TokenBucket;
|
|
6
|
+
export declare const makeConcurrencyGate: (max: number) => <T>(fn: () => Promise<T>) => Promise<T>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export type LogLevel = "debug" | "info" | "warning" | "error";
|
|
2
|
+
interface LogData {
|
|
3
|
+
message: string;
|
|
4
|
+
[key: string]: unknown;
|
|
5
|
+
}
|
|
6
|
+
export declare const sharedLogger: {
|
|
7
|
+
setLevel(level: LogLevel): void;
|
|
8
|
+
debug(logger: string, data: LogData): void;
|
|
9
|
+
info(logger: string, data: LogData): void;
|
|
10
|
+
warning(logger: string, data: LogData): void;
|
|
11
|
+
error(logger: string, data: LogData): void;
|
|
12
|
+
};
|
|
13
|
+
export declare const logger: {
|
|
14
|
+
setLevel(level: LogLevel): void;
|
|
15
|
+
debug(logger: string, data: LogData): void;
|
|
16
|
+
info(logger: string, data: LogData): void;
|
|
17
|
+
warning(logger: string, data: LogData): void;
|
|
18
|
+
error(logger: string, data: LogData): void;
|
|
19
|
+
};
|
|
20
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type PaginationCursor = string;
|
|
2
|
+
export interface PaginatedRequest {
|
|
3
|
+
cursor?: PaginationCursor;
|
|
4
|
+
}
|
|
5
|
+
export interface PaginatedResponse<T> {
|
|
6
|
+
data: T[];
|
|
7
|
+
nextCursor?: PaginationCursor;
|
|
8
|
+
}
|
|
9
|
+
export declare function createCursor(offset: number): PaginationCursor;
|
|
10
|
+
export declare function parseCursor(cursor?: PaginationCursor): number;
|
|
11
|
+
export declare function paginateArray<T>(items: T[], cursor?: PaginationCursor, limit?: number): PaginatedResponse<T>;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
export type ProgressToken = string | number;
|
|
3
|
+
export interface ProgressNotification {
|
|
4
|
+
progressToken: ProgressToken;
|
|
5
|
+
progress: number;
|
|
6
|
+
total?: number;
|
|
7
|
+
message?: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Reports progress for long-running operations.
|
|
11
|
+
*
|
|
12
|
+
* Per review finding #12: Progress notifications sent after request completion
|
|
13
|
+
* are silently ignored by the client (no handler exists for completed requests).
|
|
14
|
+
* Always send progress BEFORE returning from the handler.
|
|
15
|
+
*/
|
|
16
|
+
export declare class ProgressReporter {
|
|
17
|
+
private server;
|
|
18
|
+
private progressToken;
|
|
19
|
+
private completed;
|
|
20
|
+
constructor(server: McpServer, progressToken: ProgressToken);
|
|
21
|
+
/**
|
|
22
|
+
* Send a progress notification.
|
|
23
|
+
*
|
|
24
|
+
* @param progress - Current progress value (should increase with each call)
|
|
25
|
+
* @param total - Optional total value (for percentage calculation)
|
|
26
|
+
* @param message - Optional human-readable progress message
|
|
27
|
+
*/
|
|
28
|
+
report(progress: number, total?: number, message?: string): Promise<void>;
|
|
29
|
+
/**
|
|
30
|
+
* Mark the operation as complete.
|
|
31
|
+
* Sends final 100% progress notification.
|
|
32
|
+
* Further progress reports will be logged as warnings.
|
|
33
|
+
*/
|
|
34
|
+
complete(message?: string): Promise<void>;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Create a progress reporter for a request.
|
|
38
|
+
*
|
|
39
|
+
* @param server - The MCP server instance
|
|
40
|
+
* @param progressToken - Token from request._meta.progressToken
|
|
41
|
+
* @returns ProgressReporter instance, or null if no token provided
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```typescript
|
|
45
|
+
* const reporter = createProgressReporter(server, extra._meta?.progressToken);
|
|
46
|
+
* if (reporter) {
|
|
47
|
+
* await reporter.report(0, 100, 'Starting...');
|
|
48
|
+
* // ... do work ...
|
|
49
|
+
* await reporter.report(50, 100, 'Halfway done');
|
|
50
|
+
* // ... more work ...
|
|
51
|
+
* await reporter.complete();
|
|
52
|
+
* }
|
|
53
|
+
* return result; // Progress sent BEFORE return
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
export declare function createProgressReporter(server: McpServer, progressToken: ProgressToken | undefined): ProgressReporter | null;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Roots utilities for server→client requests.
|
|
3
|
+
*
|
|
4
|
+
* ⚠️ NODE.JS ONLY - These utilities require SDK bidirectional support
|
|
5
|
+
* (server.request()) which is not available in the Cloudflare Workers runtime.
|
|
6
|
+
* The Workers dispatcher does not support server→client requests.
|
|
7
|
+
*
|
|
8
|
+
* Per MCP spec (review finding #2):
|
|
9
|
+
* - Roots is a CLIENT capability
|
|
10
|
+
* - Servers send roots/list requests TO clients
|
|
11
|
+
* - Clients respond with filesystem locations they have access to
|
|
12
|
+
* - This enables file-based tools to know allowed paths
|
|
13
|
+
*/
|
|
14
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
15
|
+
/**
|
|
16
|
+
* A root directory or file that the client has access to.
|
|
17
|
+
* Per spec: URI MUST start with "file://"
|
|
18
|
+
*/
|
|
19
|
+
export interface Root {
|
|
20
|
+
/** The URI identifying the root. MUST start with "file://" */
|
|
21
|
+
uri: string;
|
|
22
|
+
/** Optional display name for the root */
|
|
23
|
+
name?: string;
|
|
24
|
+
/** Extension metadata */
|
|
25
|
+
_meta?: Record<string, unknown>;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Result from roots/list request.
|
|
29
|
+
*/
|
|
30
|
+
export interface ListRootsResult {
|
|
31
|
+
roots: Root[];
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Request the list of roots from the client.
|
|
35
|
+
*
|
|
36
|
+
* @param server - The MCP server instance
|
|
37
|
+
* @returns Array of Root objects representing accessible filesystem locations
|
|
38
|
+
* @throws Error if client doesn't support roots capability
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```typescript
|
|
42
|
+
* const roots = await requestRoots(server);
|
|
43
|
+
* for (const root of roots) {
|
|
44
|
+
* console.log(`Root: ${root.name ?? root.uri}`);
|
|
45
|
+
* }
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
export declare function requestRoots(server: McpServer): Promise<Root[]>;
|
|
49
|
+
/**
|
|
50
|
+
* Check if the client supports roots.
|
|
51
|
+
*
|
|
52
|
+
* @param server - The MCP server instance
|
|
53
|
+
* @returns true if client declared roots capability
|
|
54
|
+
*/
|
|
55
|
+
export declare function clientSupportsRoots(server: McpServer): boolean;
|
|
56
|
+
/**
|
|
57
|
+
* Check if the client supports roots list change notifications.
|
|
58
|
+
*
|
|
59
|
+
* @param server - The MCP server instance
|
|
60
|
+
* @returns true if client declared roots.listChanged capability
|
|
61
|
+
*/
|
|
62
|
+
export declare function clientSupportsRootsListChanged(server: McpServer): boolean;
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sampling utilities for servers to request LLM completions from clients.
|
|
3
|
+
*
|
|
4
|
+
* ⚠️ NODE.JS ONLY - These utilities require SDK bidirectional support
|
|
5
|
+
* (server.request()) which is not available in the Cloudflare Workers runtime.
|
|
6
|
+
* The Workers dispatcher does not support server→client requests.
|
|
7
|
+
*
|
|
8
|
+
* Per MCP spec:
|
|
9
|
+
* - Sampling is a CLIENT capability
|
|
10
|
+
* - Servers send sampling/createMessage requests TO clients
|
|
11
|
+
* - Clients handle the actual LLM interaction
|
|
12
|
+
* - This enables agentic behaviors in server tools
|
|
13
|
+
*/
|
|
14
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
15
|
+
/**
|
|
16
|
+
* Message content types for sampling requests.
|
|
17
|
+
*/
|
|
18
|
+
export type SamplingContent = {
|
|
19
|
+
type: "text";
|
|
20
|
+
text: string;
|
|
21
|
+
} | {
|
|
22
|
+
type: "image";
|
|
23
|
+
data: string;
|
|
24
|
+
mimeType: string;
|
|
25
|
+
} | {
|
|
26
|
+
type: "audio";
|
|
27
|
+
data: string;
|
|
28
|
+
mimeType: string;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Sampling message with role and content.
|
|
32
|
+
*/
|
|
33
|
+
export interface SamplingMessage {
|
|
34
|
+
role: "user" | "assistant";
|
|
35
|
+
content: SamplingContent;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Model preferences for sampling requests.
|
|
39
|
+
*/
|
|
40
|
+
export interface ModelPreferences {
|
|
41
|
+
/** Model name hints (evaluated in order) */
|
|
42
|
+
hints?: Array<{
|
|
43
|
+
name: string;
|
|
44
|
+
}>;
|
|
45
|
+
/** Cost priority (0-1, higher = prefer cheaper models) */
|
|
46
|
+
costPriority?: number;
|
|
47
|
+
/** Speed priority (0-1, higher = prefer faster models) */
|
|
48
|
+
speedPriority?: number;
|
|
49
|
+
/** Intelligence priority (0-1, higher = prefer more capable models) */
|
|
50
|
+
intelligencePriority?: number;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Tool choice mode for sampling requests.
|
|
54
|
+
*/
|
|
55
|
+
export interface ToolChoice {
|
|
56
|
+
/** 'auto' | 'required' | 'none' */
|
|
57
|
+
mode: "auto" | "required" | "none";
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Tool definition for sampling requests.
|
|
61
|
+
*/
|
|
62
|
+
export interface SamplingTool {
|
|
63
|
+
name: string;
|
|
64
|
+
description?: string;
|
|
65
|
+
inputSchema: Record<string, unknown>;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Sampling request parameters.
|
|
69
|
+
*/
|
|
70
|
+
export interface CreateMessageRequest {
|
|
71
|
+
messages: SamplingMessage[];
|
|
72
|
+
/** REQUIRED: Maximum tokens to generate (prevents runaway completions) */
|
|
73
|
+
maxTokens: number;
|
|
74
|
+
modelPreferences?: ModelPreferences;
|
|
75
|
+
systemPrompt?: string;
|
|
76
|
+
temperature?: number;
|
|
77
|
+
stopSequences?: string[];
|
|
78
|
+
metadata?: Record<string, unknown>;
|
|
79
|
+
/** Tools available for the LLM to use. Requires client sampling.tools capability. */
|
|
80
|
+
tools?: SamplingTool[];
|
|
81
|
+
/** Control tool usage. Can be specified without tools array to control built-in tools. */
|
|
82
|
+
toolChoice?: ToolChoice;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Sampling response from client.
|
|
86
|
+
*/
|
|
87
|
+
export interface CreateMessageResponse {
|
|
88
|
+
role: "assistant";
|
|
89
|
+
content: SamplingContent;
|
|
90
|
+
model: string;
|
|
91
|
+
stopReason?: "endTurn" | "stopSequence" | "maxTokens";
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Request LLM sampling from the client.
|
|
95
|
+
*
|
|
96
|
+
* Uses the public server.createMessage() API which handles Zod schema
|
|
97
|
+
* validation internally — avoids the _zod errors from raw request().
|
|
98
|
+
*
|
|
99
|
+
* @param server - The MCP server instance
|
|
100
|
+
* @param request - Sampling request parameters
|
|
101
|
+
* @returns The LLM response from the client
|
|
102
|
+
*
|
|
103
|
+
* @example
|
|
104
|
+
* ```typescript
|
|
105
|
+
* const response = await requestSampling(server, {
|
|
106
|
+
* messages: [
|
|
107
|
+
* {
|
|
108
|
+
* role: 'user',
|
|
109
|
+
* content: { type: 'text', text: 'What is the capital of France?' }
|
|
110
|
+
* }
|
|
111
|
+
* ],
|
|
112
|
+
* modelPreferences: {
|
|
113
|
+
* hints: [{ name: 'claude-3-sonnet' }],
|
|
114
|
+
* intelligencePriority: 0.8,
|
|
115
|
+
* speedPriority: 0.5
|
|
116
|
+
* },
|
|
117
|
+
* maxTokens: 100
|
|
118
|
+
* });
|
|
119
|
+
*
|
|
120
|
+
* console.log(response.content.text); // "The capital of France is Paris."
|
|
121
|
+
* ```
|
|
122
|
+
*/
|
|
123
|
+
export declare function requestSampling(server: McpServer, request: CreateMessageRequest): Promise<CreateMessageResponse>;
|
|
124
|
+
/**
|
|
125
|
+
* Check if the client supports sampling.
|
|
126
|
+
*
|
|
127
|
+
* @param server - The MCP server instance
|
|
128
|
+
* @returns true if client declared sampling capability
|
|
129
|
+
*/
|
|
130
|
+
export declare function clientSupportsSampling(server: McpServer): boolean;
|
|
131
|
+
/**
|
|
132
|
+
* Check if the client supports sampling with tools.
|
|
133
|
+
*
|
|
134
|
+
* @param server - The MCP server instance
|
|
135
|
+
* @returns true if client declared sampling.tools capability
|
|
136
|
+
*/
|
|
137
|
+
export declare function clientSupportsSamplingTools(server: McpServer): boolean;
|
|
138
|
+
/**
|
|
139
|
+
* Simple helper for text-only sampling requests.
|
|
140
|
+
*
|
|
141
|
+
* @param server - The MCP server instance
|
|
142
|
+
* @param prompt - User prompt text
|
|
143
|
+
* @param maxTokens - Maximum tokens to generate (REQUIRED per spec)
|
|
144
|
+
* @param options - Optional additional sampling parameters
|
|
145
|
+
* @returns The text response from the LLM
|
|
146
|
+
*
|
|
147
|
+
* @example
|
|
148
|
+
* ```typescript
|
|
149
|
+
* const answer = await requestTextCompletion(server, 'What is 2+2?', 50, {
|
|
150
|
+
* modelPreferences: { hints: [{ name: 'claude' }] }
|
|
151
|
+
* });
|
|
152
|
+
* console.log(answer); // "2+2 equals 4."
|
|
153
|
+
* ```
|
|
154
|
+
*/
|
|
155
|
+
export declare function requestTextCompletion(server: McpServer, prompt: string, maxTokens: number, options?: Omit<CreateMessageRequest, "messages" | "maxTokens">): Promise<string>;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { UnifiedConfig } from "../config/env.js";
|
|
2
|
+
export declare const makeSessionId: () => string;
|
|
3
|
+
export declare const makeEventId: () => string;
|
|
4
|
+
export declare const validateProtocolVersion: (headers: Headers, expectedVersion: string) => void;
|
|
5
|
+
export declare const validateOrigin: (headers: Headers, config: Pick<UnifiedConfig, "NODE_ENV">) => void;
|
|
6
|
+
export declare const redactSensitiveData: (obj: Record<string, unknown>) => Record<string, unknown>;
|