@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.
Files changed (85) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +187 -0
  3. package/dist/adapters/http-node/http/app.d.ts +5 -0
  4. package/dist/adapters/http-node/http/auth-app.d.ts +5 -0
  5. package/dist/adapters/http-node/http/middlewares/auth.d.ts +39 -0
  6. package/dist/adapters/http-node/http/middlewares/cors.d.ts +8 -0
  7. package/dist/adapters/http-node/http/routes/health.d.ts +5 -0
  8. package/dist/adapters/http-node/http/routes/mcp.d.ts +11 -0
  9. package/dist/adapters/http-node/middleware.security.d.ts +6 -0
  10. package/dist/adapters/http-node/routes.discovery.d.ts +6 -0
  11. package/dist/adapters/http-node/routes.oauth.d.ts +7 -0
  12. package/dist/adapters/http-worker/index.d.ts +48 -0
  13. package/dist/adapters/http-worker/mcp.handler.d.ts +24 -0
  14. package/dist/adapters/http-worker/routes.discovery.d.ts +7 -0
  15. package/dist/adapters/http-worker/routes.oauth.d.ts +8 -0
  16. package/dist/adapters/http-worker/security.d.ts +7 -0
  17. package/dist/index-1zyem3xr.js +14893 -0
  18. package/dist/index-4f4xvtt9.js +19552 -0
  19. package/dist/index-sbqy8kgq.js +3478 -0
  20. package/dist/index.d.ts +27 -0
  21. package/dist/index.js +1083 -0
  22. package/dist/mcp-server.d.ts +18 -0
  23. package/dist/runtime/node/capabilities.d.ts +2 -0
  24. package/dist/runtime/node/context.d.ts +29 -0
  25. package/dist/runtime/node/index.d.ts +5 -0
  26. package/dist/runtime/node/index.js +27 -0
  27. package/dist/runtime/node/mcp.d.ts +28 -0
  28. package/dist/runtime/node/storage/file.d.ts +44 -0
  29. package/dist/runtime/node/storage/sqlite.d.ts +213 -0
  30. package/dist/runtime/worker/index.d.ts +1 -0
  31. package/dist/runtime/worker/index.js +12 -0
  32. package/dist/shared/auth/index.d.ts +1 -0
  33. package/dist/shared/auth/strategy.d.ts +71 -0
  34. package/dist/shared/config/env.d.ts +52 -0
  35. package/dist/shared/config/index.d.ts +2 -0
  36. package/dist/shared/config/metadata.d.ts +5 -0
  37. package/dist/shared/crypto/aes-gcm.d.ts +37 -0
  38. package/dist/shared/crypto/index.d.ts +1 -0
  39. package/dist/shared/http/cors.d.ts +20 -0
  40. package/dist/shared/http/index.d.ts +2 -0
  41. package/dist/shared/http/response.d.ts +52 -0
  42. package/dist/shared/mcp/dispatcher.d.ts +81 -0
  43. package/dist/shared/mcp/index.d.ts +3 -0
  44. package/dist/shared/mcp/security.d.ts +23 -0
  45. package/dist/shared/mcp/server-internals.d.ts +79 -0
  46. package/dist/shared/oauth/cimd.d.ts +43 -0
  47. package/dist/shared/oauth/discovery-handlers.d.ts +14 -0
  48. package/dist/shared/oauth/discovery.d.ts +26 -0
  49. package/dist/shared/oauth/endpoints.d.ts +11 -0
  50. package/dist/shared/oauth/flow.d.ts +31 -0
  51. package/dist/shared/oauth/index.d.ts +9 -0
  52. package/dist/shared/oauth/input-parsers.d.ts +43 -0
  53. package/dist/shared/oauth/refresh.d.ts +61 -0
  54. package/dist/shared/oauth/ssrf.d.ts +31 -0
  55. package/dist/shared/oauth/types.d.ts +78 -0
  56. package/dist/shared/schemas/prompts.d.ts +1 -0
  57. package/dist/shared/services/http-client.d.ts +16 -0
  58. package/dist/shared/services/index.d.ts +1 -0
  59. package/dist/shared/storage/index.d.ts +4 -0
  60. package/dist/shared/storage/interface.d.ts +99 -0
  61. package/dist/shared/storage/kv.d.ts +68 -0
  62. package/dist/shared/storage/memory.d.ts +91 -0
  63. package/dist/shared/storage/singleton.d.ts +4 -0
  64. package/dist/shared/tools/echo.d.ts +16 -0
  65. package/dist/shared/tools/health.d.ts +13 -0
  66. package/dist/shared/tools/index.d.ts +4 -0
  67. package/dist/shared/tools/registry.d.ts +64 -0
  68. package/dist/shared/tools/types.d.ts +161 -0
  69. package/dist/shared/types/auth.d.ts +35 -0
  70. package/dist/shared/types/context.d.ts +79 -0
  71. package/dist/shared/types/index.d.ts +8 -0
  72. package/dist/shared/types/provider.d.ts +28 -0
  73. package/dist/shared/utils/base64.d.ts +12 -0
  74. package/dist/shared/utils/cancellation.d.ts +13 -0
  75. package/dist/shared/utils/elicitation.d.ts +247 -0
  76. package/dist/shared/utils/formatting.d.ts +106 -0
  77. package/dist/shared/utils/index.d.ts +11 -0
  78. package/dist/shared/utils/limits.d.ts +6 -0
  79. package/dist/shared/utils/logger.d.ts +20 -0
  80. package/dist/shared/utils/pagination.d.ts +11 -0
  81. package/dist/shared/utils/progress.d.ts +56 -0
  82. package/dist/shared/utils/roots.d.ts +62 -0
  83. package/dist/shared/utils/sampling.d.ts +155 -0
  84. package/dist/shared/utils/security.d.ts +6 -0
  85. 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>;