@myatkyawthu/mcp-connect 0.2.0 → 0.2.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/src/index.js CHANGED
@@ -1,33 +1,3 @@
1
- /**
2
- * MCP-Connect - Dead simple MCP (Model Context Protocol) server for exposing your app functions to AI agents
3
- *
4
- * Main entry point - exports public API
5
- *
6
- * @example
7
- * ```javascript
8
- * import { defineMCP } from 'mcp-connect';
9
- *
10
- * export default defineMCP({
11
- * name: 'My App',
12
- * version: '1.0.0',
13
- * tools: [
14
- * ['hello', async ({ name }) => `Hello ${name}!`]
15
- * ]
16
- * });
17
- * ```
18
- */
19
-
20
- // Main API exports
21
1
  export { defineMCP } from './defineMCP.js';
22
2
  export { MCPConnectServer } from './server/mcpServer.js';
23
-
24
- // Type validation utilities (for runtime type checking)
25
3
  export { isValidMCPConfig, isValidMCPTool, isValidToolDefinition } from './types/mcp.js';
26
-
27
- /**
28
- * @typedef {import('./types/mcp.js').MCPConfig} MCPConfig
29
- * @typedef {import('./types/mcp.js').MCPTool} MCPTool
30
- * @typedef {import('./types/mcp.js').ToolDefinition} ToolDefinition
31
- * @typedef {import('./types/mcp.js').MCPServerOptions} MCPServerOptions
32
- * @typedef {import('./types/mcp.js').ToolFunction} ToolFunction
33
- */
@@ -4,30 +4,15 @@ import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprot
4
4
  import { logger } from '../utils/logger.js';
5
5
  import { sanitizeErrorMessage, validateToolArguments } from '../utils/validation.js';
6
6
 
7
- // Default timeout for tool execution (30 seconds)
8
7
  const DEFAULT_TOOL_TIMEOUT = 30000;
9
8
 
10
- /**
11
- * MCP Connect Server class
12
- * Handles MCP protocol communication and tool execution
13
- */
14
9
  export class MCPConnectServer {
15
- /**
16
- * Create MCP Connect Server
17
- * @param {import('../types/mcp.js').MCPConfig} config - MCP configuration
18
- */
19
10
  constructor(config) {
20
- /** @type {import('../types/mcp.js').MCPConfig} */
21
11
  this.config = config;
22
- /** @type {boolean} */
23
12
  this.isShuttingDown = false;
24
- /** @type {Map<string, number>} */
25
13
  this.requestCounts = new Map();
26
- /** @type {number} */
27
- this.maxRequestsPerMinute = 100; // Simple rate limiting
14
+ this.maxRequestsPerMinute = 100;
28
15
 
29
- // Create MCP SDK server for STDIO transport
30
- /** @type {Server} */
31
16
  this.server = new Server(
32
17
  {
33
18
  name: config.name,
@@ -45,21 +30,13 @@ export class MCPConnectServer {
45
30
  this.setupGracefulShutdown();
46
31
  }
47
32
 
48
- /**
49
- * Set up graceful shutdown handlers
50
- */
51
33
  setupGracefulShutdown() {
52
- /**
53
- * Shutdown handler
54
- * @param {string} signal - Shutdown signal
55
- */
56
34
  const shutdown = async (signal) => {
57
35
  if (this.isShuttingDown) return;
58
36
  this.isShuttingDown = true;
59
37
 
60
38
  logger.serverShutdown(signal);
61
39
  try {
62
- // Give ongoing operations a chance to complete
63
40
  await new Promise((resolve) => setTimeout(resolve, 1000));
64
41
  process.exit(0);
65
42
  } catch (error) {
@@ -80,14 +57,6 @@ export class MCPConnectServer {
80
57
  });
81
58
  }
82
59
 
83
- /**
84
- * Execute promise with timeout
85
- * @template T
86
- * @param {Promise<T>} promise - Promise to execute
87
- * @param {number} timeoutMs - Timeout in milliseconds
88
- * @param {string} operation - Operation name for error messages
89
- * @returns {Promise<T>} Promise that resolves or rejects with timeout
90
- */
91
60
  async withTimeout(promise, timeoutMs, operation) {
92
61
  const timeoutPromise = new Promise((_, reject) => {
93
62
  setTimeout(() => {
@@ -98,11 +67,7 @@ export class MCPConnectServer {
98
67
  return Promise.race([promise, timeoutPromise]);
99
68
  }
100
69
 
101
- /**
102
- * Set up MCP request handlers
103
- */
104
70
  setupHandlers() {
105
- // List available tools
106
71
  this.server.setRequestHandler(ListToolsRequestSchema, async () => {
107
72
  return {
108
73
  tools: this.config.tools.map((tool) => ({
@@ -113,7 +78,6 @@ export class MCPConnectServer {
113
78
  };
114
79
  });
115
80
 
116
- // Execute tool calls with proper error handling and timeout
117
81
  this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
118
82
  const requestId = Math.random().toString(36).substring(2, 8);
119
83
 
@@ -121,7 +85,6 @@ export class MCPConnectServer {
121
85
  throw new Error('Server is shutting down');
122
86
  }
123
87
 
124
- // Simple rate limiting protection
125
88
  const currentMinute = Math.floor(Date.now() / 60000);
126
89
  const requestKey = `${currentMinute}`;
127
90
  const currentCount = this.requestCounts.get(requestKey) || 0;
@@ -136,7 +99,6 @@ export class MCPConnectServer {
136
99
 
137
100
  this.requestCounts.set(requestKey, currentCount + 1);
138
101
 
139
- // Clean up old request counts (keep only current and previous minute)
140
102
  for (const [key] of this.requestCounts) {
141
103
  if (parseInt(key) < currentMinute - 1) {
142
104
  this.requestCounts.delete(key);
@@ -145,10 +107,8 @@ export class MCPConnectServer {
145
107
 
146
108
  const { name, arguments: args } = request.params;
147
109
 
148
- // Log incoming request
149
110
  logger.traceRequest('tools/call', { name, args }, requestId);
150
111
 
151
- // Validate request
152
112
  if (!name || typeof name !== 'string') {
153
113
  const error = new Error('Tool name is required and must be a string');
154
114
  logger.traceError('tools/call', error, requestId);
@@ -168,10 +128,8 @@ export class MCPConnectServer {
168
128
  logger.toolExecutionStart(name, args, requestId);
169
129
 
170
130
  try {
171
- // Validate and sanitize arguments
172
131
  const validatedArgs = validateToolArguments(args);
173
132
 
174
- // Execute tool with timeout and performance tracking
175
133
  const toolPromise = Promise.resolve(tool.handler(validatedArgs));
176
134
  const result = await logger.timeAsync(
177
135
  `Tool "${name}" execution`,
@@ -179,9 +137,8 @@ export class MCPConnectServer {
179
137
  name
180
138
  );
181
139
 
182
- // Handle different result types with size limits
183
140
  let content;
184
- const MAX_RESPONSE_SIZE = 1024 * 1024; // 1MB limit
141
+ const MAX_RESPONSE_SIZE = 1024 * 1024;
185
142
 
186
143
  if (typeof result === 'string') {
187
144
  content = result;
@@ -189,24 +146,17 @@ export class MCPConnectServer {
189
146
  content = 'null';
190
147
  } else {
191
148
  try {
192
- // Handle circular references and large objects
193
- const jsonString = JSON.stringify(
194
- result,
195
- (key, value) => {
196
- // Handle circular references
197
- if (typeof value === 'object' && value !== null) {
198
- if (this.seenObjects && this.seenObjects.has(value)) {
199
- return '[Circular Reference]';
200
- }
201
- if (!this.seenObjects) this.seenObjects = new WeakSet();
202
- this.seenObjects.add(value);
149
+ const jsonString = JSON.stringify(result, (key, value) => {
150
+ if (typeof value === 'object' && value !== null) {
151
+ if (this.seenObjects && this.seenObjects.has(value)) {
152
+ return '[Circular Reference]';
203
153
  }
204
- return value;
205
- },
206
- 2
207
- );
154
+ if (!this.seenObjects) this.seenObjects = new WeakSet();
155
+ this.seenObjects.add(value);
156
+ }
157
+ return value;
158
+ }, 2);
208
159
 
209
- // Reset circular reference tracker
210
160
  this.seenObjects = null;
211
161
 
212
162
  content = jsonString;
@@ -216,7 +166,6 @@ export class MCPConnectServer {
216
166
  }
217
167
  }
218
168
 
219
- // Check response size and truncate if necessary
220
169
  if (content.length > MAX_RESPONSE_SIZE) {
221
170
  const truncated = content.substring(0, MAX_RESPONSE_SIZE - 100);
222
171
  content = truncated + '\n\n[Response truncated - exceeded 1MB limit]';
@@ -243,23 +192,16 @@ export class MCPConnectServer {
243
192
  logger.toolExecutionError(name, error, duration, requestId);
244
193
  logger.traceError('tools/call', error, requestId);
245
194
 
246
- // Return MCP-compliant error with sanitized message
247
195
  const sanitizedMessage = sanitizeErrorMessage(error);
248
196
  throw new Error(`Tool "${name}" failed: ${sanitizedMessage}`);
249
197
  }
250
198
  });
251
199
  }
252
200
 
253
- /**
254
- * Start the MCP server with STDIO transport
255
- * @returns {Promise<void>} Promise that resolves when server starts
256
- * @throws {Error} If server fails to start
257
- */
258
201
  async start() {
259
202
  try {
260
203
  const transport = new StdioServerTransport();
261
204
 
262
- // Enhanced error handling for transport
263
205
  transport.onclose = () => {
264
206
  if (!this.isShuttingDown) {
265
207
  logger.warn('STDIO transport closed unexpectedly - AI client may have disconnected');
@@ -270,7 +212,6 @@ export class MCPConnectServer {
270
212
  transport.onerror = (error) => {
271
213
  logger.error('STDIO transport error', error);
272
214
 
273
- // Provide helpful guidance for common transport errors
274
215
  if (error && typeof error === 'object') {
275
216
  const errorStr = error.toString();
276
217
 
@@ -287,7 +228,6 @@ export class MCPConnectServer {
287
228
  }
288
229
  };
289
230
 
290
- // Handle process stdio errors
291
231
  process.stdin.on('error', (error) => {
292
232
  if (!this.isShuttingDown) {
293
233
  logger.error('STDIN error', error);
@@ -307,7 +247,6 @@ export class MCPConnectServer {
307
247
  } catch (error) {
308
248
  logger.error('Failed to start MCP server', error);
309
249
 
310
- // Enhanced error guidance
311
250
  if (error instanceof Error) {
312
251
  const errorMsg = error.message;
313
252
 
@@ -333,13 +272,8 @@ export class MCPConnectServer {
333
272
  }
334
273
  }
335
274
 
336
- /**
337
- * Stop the MCP server
338
- * @returns {Promise<void>} Promise that resolves when server stops
339
- */
340
275
  async stop() {
341
276
  this.isShuttingDown = true;
342
- // STDIO transport doesn't need explicit stopping
343
277
  logger.info('MCP server stopped');
344
278
  }
345
279
  }
package/src/types/mcp.js CHANGED
@@ -1,60 +1,3 @@
1
- /**
2
- * MCP-compliant types using official SDK
3
- * This file contains JSDoc type definitions for MCP-Connect
4
- */
5
-
6
- /**
7
- * @typedef {Object} MCPTool
8
- * @property {string} name - Tool name
9
- * @property {string} description - Tool description
10
- * @property {Record<string, any>} inputSchema - JSON Schema for input validation
11
- * @property {function(Record<string, any>): Promise<any>|any} handler - Tool execution function
12
- */
13
-
14
- /**
15
- * @typedef {Object} MCPConfig
16
- * @property {string} name - Server name
17
- * @property {string} version - Server version
18
- * @property {string} [description] - Server description
19
- * @property {MCPTool[]} tools - Array of MCP tools
20
- */
21
-
22
- /**
23
- * @typedef {Object} MCPServerOptions
24
- * @property {MCPConfig} config - MCP configuration
25
- */
26
-
27
- /**
28
- * Legacy types for backward compatibility
29
- */
30
-
31
- /**
32
- * @typedef {function(...any[]): Promise<any>|any} ToolFunction
33
- */
34
-
35
- /**
36
- * Tool definition - supports both tuple and object formats
37
- * @typedef {[string, ToolFunction]|{name: string, handler: ToolFunction, description?: string, schema?: Record<string, any>}} ToolDefinition
38
- *
39
- * Tuple format: [name, handler]
40
- * @example ['hello', async (args) => `Hello ${args.name}!`]
41
- *
42
- * Object format: {name, handler, description?, schema?}
43
- * @example {
44
- * name: 'hello',
45
- * handler: async (args) => `Hello ${args.name}!`,
46
- * description: 'Greet a user',
47
- * schema: { type: 'object', properties: { name: { type: 'string' } } }
48
- * }
49
- */
50
-
51
- // Runtime validation functions for type checking
52
-
53
- /**
54
- * Validate MCPTool object
55
- * @param {any} tool - Tool to validate
56
- * @returns {boolean} Whether the tool is valid
57
- */
58
1
  export function isValidMCPTool(tool) {
59
2
  return (
60
3
  tool &&
@@ -66,11 +9,6 @@ export function isValidMCPTool(tool) {
66
9
  );
67
10
  }
68
11
 
69
- /**
70
- * Validate MCPConfig object
71
- * @param {any} config - Config to validate
72
- * @returns {boolean} Whether the config is valid
73
- */
74
12
  export function isValidMCPConfig(config) {
75
13
  return (
76
14
  config &&
@@ -82,19 +20,12 @@ export function isValidMCPConfig(config) {
82
20
  );
83
21
  }
84
22
 
85
- /**
86
- * Validate ToolDefinition (tuple or object format)
87
- * @param {any} toolDef - Tool definition to validate
88
- * @returns {boolean} Whether the tool definition is valid
89
- */
90
23
  export function isValidToolDefinition(toolDef) {
91
24
  if (Array.isArray(toolDef)) {
92
- // Tuple format: [name, handler]
93
25
  return (
94
26
  toolDef.length === 2 && typeof toolDef[0] === 'string' && typeof toolDef[1] === 'function'
95
27
  );
96
28
  } else if (toolDef && typeof toolDef === 'object') {
97
- // Object format: {name, handler, description?, schema?}
98
29
  return (
99
30
  typeof toolDef.name === 'string' &&
100
31
  typeof toolDef.handler === 'function' &&