@mctx-ai/mcp-server 0.3.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.
@@ -0,0 +1,733 @@
1
+ /**
2
+ * @mctx-ai/mcp-server TypeScript Definitions
3
+ *
4
+ * Build MCP servers with an Express-like API - no protocol knowledge required.
5
+ */
6
+
7
+ /// <reference types="node" />
8
+
9
+ // ============================================================================
10
+ // Core Server Types
11
+ // ============================================================================
12
+
13
+ /**
14
+ * MCP Server instance with tool, resource, and prompt registration methods.
15
+ * Compatible with Cloudflare Workers fetch handler.
16
+ */
17
+ export interface Server {
18
+ /**
19
+ * Register a tool handler.
20
+ * Tools can be synchronous or asynchronous functions, or generator functions for progress tracking.
21
+ *
22
+ * @param name - Tool name (must be unique)
23
+ * @param handler - Tool handler function
24
+ * @returns Server instance for chaining
25
+ *
26
+ * @example
27
+ * ```typescript
28
+ * server.tool('add', (args: { a: number; b: number }) => {
29
+ * return args.a + args.b;
30
+ * });
31
+ * ```
32
+ *
33
+ * @example
34
+ * // Generator tool with progress tracking
35
+ * ```typescript
36
+ * server.tool('migrate', function* (args: { sourceDb: string; targetDb: string }) {
37
+ * const step = createProgress(5);
38
+ * yield step(); // Progress: 1/5
39
+ * // ... do work
40
+ * return "Migration complete";
41
+ * });
42
+ * ```
43
+ */
44
+ tool(name: string, handler: ToolHandler | GeneratorToolHandler): Server;
45
+
46
+ /**
47
+ * Register a resource handler.
48
+ * Resources can be static URIs or URI templates with {param} placeholders.
49
+ *
50
+ * @param uri - Resource URI (may contain {param} templates)
51
+ * @param handler - Resource handler function
52
+ * @returns Server instance for chaining
53
+ *
54
+ * @example
55
+ * ```typescript
56
+ * // Static resource
57
+ * server.resource('db://customers/schema', () => {
58
+ * return JSON.stringify({ ... });
59
+ * });
60
+ *
61
+ * // Dynamic resource with template
62
+ * server.resource('db://customers/{id}', (params) => {
63
+ * return getCustomer(params.id);
64
+ * });
65
+ * ```
66
+ */
67
+ resource(uri: string, handler: ResourceHandler): Server;
68
+
69
+ /**
70
+ * Register a prompt handler.
71
+ * Prompts return messages for LLM conversation initialization.
72
+ *
73
+ * @param name - Prompt name (must be unique)
74
+ * @param handler - Prompt handler function
75
+ * @returns Server instance for chaining
76
+ *
77
+ * @example
78
+ * ```typescript
79
+ * server.prompt('code-review', (args: { code: string }) => {
80
+ * return conversation(({ user }) => [
81
+ * user.say("Review this code:"),
82
+ * user.say(args.code),
83
+ * ]);
84
+ * });
85
+ * ```
86
+ */
87
+ prompt(name: string, handler: PromptHandler): Server;
88
+
89
+ /**
90
+ * Cloudflare Worker fetch handler.
91
+ * Processes JSON-RPC 2.0 requests over HTTP POST.
92
+ *
93
+ * @param request - HTTP request object
94
+ * @param env - Environment variables (optional)
95
+ * @param ctx - Execution context (optional)
96
+ * @returns HTTP response
97
+ *
98
+ * @example
99
+ * ```typescript
100
+ * // Cloudflare Worker
101
+ * export default {
102
+ * fetch: server.fetch,
103
+ * };
104
+ * ```
105
+ */
106
+ fetch(request: Request, env?: any, ctx?: any): Promise<Response>;
107
+ }
108
+
109
+ /**
110
+ * Creates an MCP server instance.
111
+ *
112
+ * @returns Server instance with registration methods and fetch handler
113
+ *
114
+ * @example
115
+ * ```typescript
116
+ * import { createServer, T } from '@mctx-ai/mcp-server';
117
+ *
118
+ * const server = createServer();
119
+ *
120
+ * server.tool('greet', (args: { name: string }) => {
121
+ * return `Hello, ${args.name}!`;
122
+ * });
123
+ *
124
+ * export default { fetch: server.fetch };
125
+ * ```
126
+ */
127
+ export function createServer(): Server;
128
+
129
+ // ============================================================================
130
+ // Handler Types
131
+ // ============================================================================
132
+
133
+ /**
134
+ * Tool handler function (non-generator).
135
+ * Receives arguments and optional ask function for LLM sampling.
136
+ *
137
+ * @param args - Tool arguments (validated against handler.input schema)
138
+ * @param ask - Optional LLM sampling function (null if not supported)
139
+ * @returns Tool result (string, object, or Promise thereof)
140
+ */
141
+ export type ToolHandler = {
142
+ (args: Record<string, any>, ask?: AskFunction | null): any | Promise<any>;
143
+ /** Tool description for documentation */
144
+ description?: string;
145
+ /** Input schema definition using T types */
146
+ input?: Record<string, SchemaDefinition>;
147
+ /** MIME type for binary results (optional) */
148
+ mimeType?: string;
149
+ };
150
+
151
+ /**
152
+ * Generator tool handler function (for progress tracking).
153
+ * Yields progress notifications and returns final result.
154
+ *
155
+ * @param args - Tool arguments
156
+ * @param ask - Optional LLM sampling function
157
+ * @yields Progress notifications or intermediate values
158
+ * @returns Final tool result
159
+ *
160
+ * @example
161
+ * ```typescript
162
+ * function* migrate(args: { tables: string[] }): Generator<ProgressNotification, string> {
163
+ * const step = createProgress(args.tables.length);
164
+ * for (const table of args.tables) {
165
+ * yield step();
166
+ * // ... process table
167
+ * }
168
+ * return "Migration complete";
169
+ * }
170
+ * ```
171
+ */
172
+ export type GeneratorToolHandler = {
173
+ (args: Record<string, any>, ask?: AskFunction | null): Generator<any, any, any> | AsyncGenerator<any, any, any>;
174
+ description?: string;
175
+ input?: Record<string, SchemaDefinition>;
176
+ mimeType?: string;
177
+ };
178
+
179
+ /**
180
+ * Resource handler function.
181
+ * Returns resource content (string, binary data, or object).
182
+ *
183
+ * @param params - Extracted URI template parameters (e.g., { id: '123' })
184
+ * @param ask - Optional LLM sampling function
185
+ * @returns Resource content
186
+ */
187
+ export type ResourceHandler = {
188
+ (params: Record<string, string>, ask?: AskFunction | null): any | Promise<any>;
189
+ /** Resource name for display */
190
+ name?: string;
191
+ /** Resource description */
192
+ description?: string;
193
+ /** MIME type (default: 'text/plain') */
194
+ mimeType?: string;
195
+ };
196
+
197
+ /**
198
+ * Prompt handler function.
199
+ * Returns messages for LLM conversation or a conversation result.
200
+ *
201
+ * @param args - Prompt arguments
202
+ * @param ask - Optional LLM sampling function
203
+ * @returns Prompt messages (string, conversation result, or message array)
204
+ */
205
+ export type PromptHandler = {
206
+ (args: Record<string, any>, ask?: AskFunction | null): string | ConversationResult | Message[] | Promise<string | ConversationResult | Message[]>;
207
+ /** Prompt description */
208
+ description?: string;
209
+ /** Input schema definition using T types */
210
+ input?: Record<string, SchemaDefinition>;
211
+ };
212
+
213
+ /**
214
+ * LLM sampling function.
215
+ * Allows tools to request AI completions from the client.
216
+ * Overloaded to accept either a simple string prompt or advanced options.
217
+ *
218
+ * @param prompt - Simple text prompt
219
+ * @returns LLM response content
220
+ *
221
+ * @example
222
+ * ```typescript
223
+ * // Simple usage
224
+ * const summary = await ask("Summarize this document: " + doc);
225
+ * ```
226
+ *
227
+ * @example
228
+ * // Advanced usage
229
+ * ```typescript
230
+ * const result = await ask({
231
+ * messages: [
232
+ * { role: "user", content: { type: "text", text: "What is the capital of France?" } }
233
+ * ],
234
+ * modelPreferences: {
235
+ * hints: [{ name: "claude-3-5-sonnet" }]
236
+ * },
237
+ * maxTokens: 1000,
238
+ * });
239
+ * ```
240
+ */
241
+ export type AskFunction = {
242
+ (prompt: string): Promise<string | Record<string, unknown>>;
243
+ (options: SamplingOptions): Promise<string | Record<string, unknown>>;
244
+ };
245
+
246
+ /**
247
+ * Options for LLM sampling requests.
248
+ */
249
+ export interface SamplingOptions {
250
+ /** Array of conversation messages */
251
+ messages: Message[];
252
+ /** Model preferences (optional) */
253
+ modelPreferences?: {
254
+ hints?: Array<{ name: string }>;
255
+ };
256
+ /** System prompt (optional) */
257
+ systemPrompt?: string;
258
+ /** Maximum tokens to generate (optional) */
259
+ maxTokens?: number;
260
+ /** Temperature for sampling (optional, 0.0-1.0) */
261
+ temperature?: number;
262
+ /** Top-p sampling parameter (optional, 0.0-1.0) */
263
+ topP?: number;
264
+ /** Stop sequences (optional) */
265
+ stopSequences?: string[];
266
+ }
267
+
268
+ // ============================================================================
269
+ // JSON Schema Type System (T)
270
+ // ============================================================================
271
+
272
+ /**
273
+ * Schema definition created by T type builders.
274
+ * Represents a JSON Schema property with optional metadata.
275
+ */
276
+ export interface SchemaDefinition {
277
+ type: 'string' | 'number' | 'boolean' | 'array' | 'object';
278
+ description?: string;
279
+ enum?: any[];
280
+ default?: any;
281
+ // String constraints
282
+ minLength?: number;
283
+ maxLength?: number;
284
+ pattern?: string;
285
+ format?: string;
286
+ // Number constraints
287
+ minimum?: number;
288
+ maximum?: number;
289
+ // Array constraints
290
+ items?: SchemaDefinition;
291
+ // Object constraints
292
+ properties?: Record<string, SchemaDefinition>;
293
+ required?: string[];
294
+ additionalProperties?: boolean | SchemaDefinition;
295
+ // Internal metadata (removed by buildInputSchema)
296
+ _required?: boolean;
297
+ }
298
+
299
+ /**
300
+ * Options for string type schemas.
301
+ */
302
+ export interface StringOptions {
303
+ /** Mark field as required (metadata for buildInputSchema) */
304
+ required?: boolean;
305
+ /** Field description */
306
+ description?: string;
307
+ /** Allowed values (enum) */
308
+ enum?: string[];
309
+ /** Default value */
310
+ default?: string;
311
+ /** Minimum string length */
312
+ minLength?: number;
313
+ /** Maximum string length */
314
+ maxLength?: number;
315
+ /** Regex pattern */
316
+ pattern?: string;
317
+ /** Format hint (e.g., 'email', 'uri', 'date-time') */
318
+ format?: string;
319
+ }
320
+
321
+ /**
322
+ * Options for number type schemas.
323
+ */
324
+ export interface NumberOptions {
325
+ /** Mark field as required */
326
+ required?: boolean;
327
+ /** Field description */
328
+ description?: string;
329
+ /** Allowed values (enum) */
330
+ enum?: number[];
331
+ /** Default value */
332
+ default?: number;
333
+ /** Minimum value (maps to 'minimum') */
334
+ min?: number;
335
+ /** Maximum value (maps to 'maximum') */
336
+ max?: number;
337
+ }
338
+
339
+ /**
340
+ * Options for boolean type schemas.
341
+ */
342
+ export interface BooleanOptions {
343
+ /** Mark field as required */
344
+ required?: boolean;
345
+ /** Field description */
346
+ description?: string;
347
+ /** Default value */
348
+ default?: boolean;
349
+ }
350
+
351
+ /**
352
+ * Options for array type schemas.
353
+ */
354
+ export interface ArrayOptions {
355
+ /** Mark field as required */
356
+ required?: boolean;
357
+ /** Field description */
358
+ description?: string;
359
+ /** Schema for array items */
360
+ items?: SchemaDefinition;
361
+ /** Default value */
362
+ default?: any[];
363
+ }
364
+
365
+ /**
366
+ * Options for object type schemas.
367
+ */
368
+ export interface ObjectOptions {
369
+ /** Mark field as required */
370
+ required?: boolean;
371
+ /** Field description */
372
+ description?: string;
373
+ /** Nested property schemas */
374
+ properties?: Record<string, SchemaDefinition>;
375
+ /** Allow additional properties (boolean or schema) */
376
+ additionalProperties?: boolean | SchemaDefinition;
377
+ /** Default value */
378
+ default?: Record<string, any>;
379
+ }
380
+
381
+ /**
382
+ * T - JSON Schema type system for tool and prompt inputs.
383
+ * Provides factory methods to build JSON Schema objects with a clean API.
384
+ *
385
+ * @example
386
+ * ```typescript
387
+ * import { T } from '@mctx-ai/mcp-server';
388
+ *
389
+ * const handler = {
390
+ * input: {
391
+ * name: T.string({ required: true, description: "User name" }),
392
+ * age: T.number({ min: 0, max: 150 }),
393
+ * role: T.string({ enum: ['admin', 'user', 'guest'] }),
394
+ * tags: T.array({ items: T.string() }),
395
+ * metadata: T.object({
396
+ * properties: {
397
+ * createdAt: T.string({ format: 'date-time' }),
398
+ * },
399
+ * }),
400
+ * },
401
+ * };
402
+ * ```
403
+ */
404
+ export const T: {
405
+ /**
406
+ * Creates a string type schema.
407
+ *
408
+ * @param options - Schema options
409
+ * @returns JSON Schema object
410
+ */
411
+ string(options?: StringOptions): SchemaDefinition;
412
+
413
+ /**
414
+ * Creates a number type schema.
415
+ *
416
+ * @param options - Schema options
417
+ * @returns JSON Schema object
418
+ */
419
+ number(options?: NumberOptions): SchemaDefinition;
420
+
421
+ /**
422
+ * Creates a boolean type schema.
423
+ *
424
+ * @param options - Schema options
425
+ * @returns JSON Schema object
426
+ */
427
+ boolean(options?: BooleanOptions): SchemaDefinition;
428
+
429
+ /**
430
+ * Creates an array type schema.
431
+ *
432
+ * @param options - Schema options
433
+ * @returns JSON Schema object
434
+ */
435
+ array(options?: ArrayOptions): SchemaDefinition;
436
+
437
+ /**
438
+ * Creates an object type schema.
439
+ *
440
+ * @param options - Schema options
441
+ * @returns JSON Schema object
442
+ */
443
+ object(options?: ObjectOptions): SchemaDefinition;
444
+ };
445
+
446
+ /**
447
+ * Builds a complete MCP input schema from handler input definition.
448
+ * Extracts required fields and removes internal metadata.
449
+ *
450
+ * @param input - Handler input definition using T types
451
+ * @returns Valid JSON Schema for MCP inputSchema
452
+ *
453
+ * @example
454
+ * ```typescript
455
+ * const inputSchema = buildInputSchema({
456
+ * name: T.string({ required: true }),
457
+ * age: T.number(),
458
+ * });
459
+ * // => { type: 'object', properties: { name: {...}, age: {...} }, required: ['name'] }
460
+ * ```
461
+ */
462
+ export function buildInputSchema(input?: Record<string, SchemaDefinition>): {
463
+ type: 'object';
464
+ properties: Record<string, SchemaDefinition>;
465
+ required?: string[];
466
+ };
467
+
468
+ // ============================================================================
469
+ // Conversation Builder
470
+ // ============================================================================
471
+
472
+ /**
473
+ * Message object in MCP format.
474
+ */
475
+ export interface Message {
476
+ /** Message role */
477
+ role: 'user' | 'assistant';
478
+ /** Message content */
479
+ content: TextContent | ImageContent | ResourceContent;
480
+ }
481
+
482
+ /**
483
+ * Text content type.
484
+ */
485
+ export interface TextContent {
486
+ type: 'text';
487
+ text: string;
488
+ }
489
+
490
+ /**
491
+ * Image content type (base64-encoded).
492
+ */
493
+ export interface ImageContent {
494
+ type: 'image';
495
+ data: string;
496
+ mimeType: string;
497
+ }
498
+
499
+ /**
500
+ * Resource content type (embedded resource).
501
+ */
502
+ export interface ResourceContent {
503
+ type: 'resource';
504
+ resource: {
505
+ uri: string;
506
+ text: string;
507
+ };
508
+ }
509
+
510
+ /**
511
+ * Result returned by conversation() builder.
512
+ */
513
+ export interface ConversationResult {
514
+ messages: Message[];
515
+ }
516
+
517
+ /**
518
+ * Role helper object provided to conversation builder.
519
+ */
520
+ export interface RoleHelper {
521
+ /**
522
+ * Add a text message.
523
+ *
524
+ * @param text - The text content
525
+ * @returns MCP message object
526
+ */
527
+ say(text: string): Message;
528
+
529
+ /**
530
+ * Attach an image (base64 data).
531
+ *
532
+ * @param data - Base64-encoded image data
533
+ * @param mimeType - MIME type (e.g., "image/png", "image/jpeg")
534
+ * @returns MCP message object
535
+ */
536
+ attach(data: string, mimeType: string): Message;
537
+
538
+ /**
539
+ * Embed a resource by URI.
540
+ *
541
+ * @param uri - The resource URI to embed
542
+ * @returns MCP message object
543
+ */
544
+ embed(uri: string): Message;
545
+ }
546
+
547
+ /**
548
+ * Conversation builder helpers.
549
+ */
550
+ export interface ConversationHelpers {
551
+ /** User role helper */
552
+ user: RoleHelper;
553
+ /** Assistant role helper */
554
+ ai: RoleHelper;
555
+ }
556
+
557
+ /**
558
+ * Creates a conversation using a builder function.
559
+ * Provides clean API for constructing MCP prompt messages.
560
+ *
561
+ * @param builderFn - Function that receives { user, ai } helpers
562
+ * @returns MCP prompt result: { messages: [...] }
563
+ *
564
+ * @example
565
+ * ```typescript
566
+ * const result = conversation(({ user, ai }) => [
567
+ * user.say("What's in this image?"),
568
+ * user.attach(imageData, "image/png"),
569
+ * ai.say("I see a customer schema..."),
570
+ * ]);
571
+ * ```
572
+ */
573
+ export function conversation(
574
+ builderFn: (helpers: ConversationHelpers) => Message[]
575
+ ): ConversationResult;
576
+
577
+ // ============================================================================
578
+ // Progress Tracking
579
+ // ============================================================================
580
+
581
+ /**
582
+ * Progress notification object.
583
+ * Yielded by generator tools to report progress.
584
+ */
585
+ export interface ProgressNotification {
586
+ type: 'progress';
587
+ /** Current step number (1-indexed) */
588
+ progress: number;
589
+ /** Total steps (optional, for determinate progress) */
590
+ total?: number;
591
+ }
592
+
593
+ /**
594
+ * Progress step function.
595
+ * Call to generate next progress notification.
596
+ */
597
+ export type StepFunction = () => ProgressNotification;
598
+
599
+ /**
600
+ * Creates a progress step function for generator-based tools.
601
+ * Each call auto-increments the progress counter.
602
+ *
603
+ * @param total - Total number of steps (optional, for determinate progress)
604
+ * @returns Step function that returns progress notification objects
605
+ *
606
+ * @example
607
+ * ```typescript
608
+ * // Determinate progress (with known total)
609
+ * function* migrate(args: { tables: string[] }) {
610
+ * const step = createProgress(args.tables.length);
611
+ * for (const table of args.tables) {
612
+ * yield step(); // { type: "progress", progress: 1, total: 5 }
613
+ * await copyTable(table);
614
+ * }
615
+ * return "Migration complete";
616
+ * }
617
+ * ```
618
+ *
619
+ * @example
620
+ * ```typescript
621
+ * // Indeterminate progress (no total)
622
+ * function* processQueue() {
623
+ * const step = createProgress();
624
+ * while (hasMessages()) {
625
+ * yield step(); // { type: "progress", progress: 1 }
626
+ * await processMessage();
627
+ * }
628
+ * return "Queue processed";
629
+ * }
630
+ * ```
631
+ */
632
+ export function createProgress(total?: number): StepFunction;
633
+
634
+ /**
635
+ * Default configuration for generator guardrails.
636
+ * Server uses these to prevent runaway generators.
637
+ */
638
+ export const PROGRESS_DEFAULTS: {
639
+ /** Maximum execution time in milliseconds (60 seconds) */
640
+ maxExecutionTime: number;
641
+ /** Maximum number of yields (10,000) */
642
+ maxYields: number;
643
+ };
644
+
645
+ // ============================================================================
646
+ // Logging
647
+ // ============================================================================
648
+
649
+ /**
650
+ * Log severity level (RFC 5424).
651
+ */
652
+ export type LogLevel = 'debug' | 'info' | 'notice' | 'warning' | 'error' | 'critical' | 'alert' | 'emergency';
653
+
654
+ /**
655
+ * Log object with methods for each severity level.
656
+ * Creates log notifications that are buffered and sent by the server.
657
+ *
658
+ * @example
659
+ * ```typescript
660
+ * import { log } from '@mctx-ai/mcp-server';
661
+ *
662
+ * log.debug('Variable value:', { x: 42 });
663
+ * log.info('Server started on port 3000');
664
+ * log.warning('Rate limit approaching');
665
+ * log.error('Database connection failed', error);
666
+ * log.critical('System out of memory');
667
+ * ```
668
+ */
669
+ export const log: {
670
+ /**
671
+ * Debug-level message (lowest severity).
672
+ * Used for detailed debugging information.
673
+ *
674
+ * @param data - Log data (any JSON-serializable value)
675
+ */
676
+ debug(data: any): void;
677
+
678
+ /**
679
+ * Informational message.
680
+ * Used for general informational messages.
681
+ *
682
+ * @param data - Log data
683
+ */
684
+ info(data: any): void;
685
+
686
+ /**
687
+ * Notice - normal but significant condition.
688
+ * Used for important events that are not errors.
689
+ *
690
+ * @param data - Log data
691
+ */
692
+ notice(data: any): void;
693
+
694
+ /**
695
+ * Warning condition.
696
+ * Used for warnings that don't prevent operation.
697
+ *
698
+ * @param data - Log data
699
+ */
700
+ warning(data: any): void;
701
+
702
+ /**
703
+ * Error condition.
704
+ * Used for errors that affect functionality.
705
+ *
706
+ * @param data - Log data
707
+ */
708
+ error(data: any): void;
709
+
710
+ /**
711
+ * Critical condition.
712
+ * Used for critical conditions requiring immediate attention.
713
+ *
714
+ * @param data - Log data
715
+ */
716
+ critical(data: any): void;
717
+
718
+ /**
719
+ * Alert - action must be taken immediately.
720
+ * Used for conditions requiring immediate operator intervention.
721
+ *
722
+ * @param data - Log data
723
+ */
724
+ alert(data: any): void;
725
+
726
+ /**
727
+ * Emergency - system is unusable.
728
+ * Used for system-wide failures.
729
+ *
730
+ * @param data - Log data
731
+ */
732
+ emergency(data: any): void;
733
+ };