converse-mcp-server 1.1.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -71,9 +71,11 @@ XAI_BASE_URL=https://api.x.ai/v1
71
71
  | **Google** | [makersuite.google.com/app/apikey](https://makersuite.google.com/app/apikey) | `AIzaSy...` |
72
72
  | **X.AI** | [console.x.ai](https://console.x.ai/) | `xai-...` |
73
73
 
74
- ### 3. MCP Client Configuration
74
+ ### 3. Installing in Claude Code or Claude Desktop
75
75
 
76
- Add to your MCP client configuration (e.g., Claude Desktop):
76
+ There are several ways to add the Converse MCP Server to Claude:
77
+
78
+ #### Option A: Using NPX (Recommended)
77
79
 
78
80
  ```json
79
81
  {
@@ -84,13 +86,95 @@ Add to your MCP client configuration (e.g., Claude Desktop):
84
86
  "env": {
85
87
  "OPENAI_API_KEY": "your_key_here",
86
88
  "GOOGLE_API_KEY": "your_key_here",
87
- "XAI_API_KEY": "your_key_here"
89
+ "XAI_API_KEY": "your_key_here",
90
+ "MAX_MCP_OUTPUT_TOKENS": "200000"
91
+ }
92
+ }
93
+ }
94
+ }
95
+ ```
96
+
97
+ #### Option B: Using NPX with stdio transport
98
+
99
+ ```json
100
+ {
101
+ "mcpServers": {
102
+ "converse": {
103
+ "command": "npx",
104
+ "args": ["FallDownTheSystem/converse", "--transport", "stdio"],
105
+ "env": {
106
+ "OPENAI_API_KEY": "your_key_here",
107
+ "GOOGLE_API_KEY": "your_key_here",
108
+ "XAI_API_KEY": "your_key_here",
109
+ "MAX_MCP_OUTPUT_TOKENS": "200000"
88
110
  }
89
111
  }
90
112
  }
91
113
  }
92
114
  ```
93
115
 
116
+ #### Option C: Direct Node.js execution
117
+
118
+ ```json
119
+ {
120
+ "mcpServers": {
121
+ "converse": {
122
+ "command": "node",
123
+ "args": [
124
+ "C:\\Users\\YourUsername\\Documents\\Projects\\converse\\src\\index.js",
125
+ "--transport",
126
+ "stdio"
127
+ ],
128
+ "env": {
129
+ "OPENAI_API_KEY": "your_key_here",
130
+ "GOOGLE_API_KEY": "your_key_here",
131
+ "XAI_API_KEY": "your_key_here",
132
+ "MAX_MCP_OUTPUT_TOKENS": "200000"
133
+ }
134
+ }
135
+ }
136
+ }
137
+ ```
138
+
139
+ #### Option D: Using environment variable for transport
140
+
141
+ ```json
142
+ {
143
+ "mcpServers": {
144
+ "converse": {
145
+ "command": "npx",
146
+ "args": ["FallDownTheSystem/converse"],
147
+ "env": {
148
+ "MCP_TRANSPORT": "stdio",
149
+ "OPENAI_API_KEY": "your_key_here",
150
+ "GOOGLE_API_KEY": "your_key_here",
151
+ "XAI_API_KEY": "your_key_here",
152
+ "MAX_MCP_OUTPUT_TOKENS": "200000"
153
+ }
154
+ }
155
+ }
156
+ }
157
+ ```
158
+
159
+ #### Installation Steps
160
+
161
+ 1. **For Claude Code**:
162
+ - Open the command palette (Ctrl/Cmd + Shift + P)
163
+ - Run "Claude Code: Edit MCP Settings"
164
+ - Add one of the configurations above
165
+
166
+ 2. **For Claude Desktop**:
167
+ - Navigate to Settings → Developer → MCP Servers
168
+ - Click "Add Server" and paste one of the configurations above
169
+
170
+ 3. **Manual Configuration**:
171
+ - The configuration file is typically located at:
172
+ - Windows: `%APPDATA%\Claude\claude_desktop_config.json`
173
+ - macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
174
+ - Linux: `~/.config/Claude/claude_desktop_config.json`
175
+
176
+ For more detailed instructions, see the [official MCP configuration guide](https://docs.anthropic.com/en/docs/claude-code/mcp#configure-mcp-servers).
177
+
94
178
  ## 🛠️ Available Tools
95
179
 
96
180
  ### 1. Chat Tool
@@ -129,6 +213,23 @@ Multi-provider parallel execution with cross-model feedback.
129
213
  }
130
214
  ```
131
215
 
216
+ ## 📚 Help & Documentation
217
+
218
+ The Converse MCP Server provides built-in help through:
219
+
220
+ ### Help Prompt
221
+ Access comprehensive documentation directly in Claude:
222
+ - `/converse:help` - Full documentation
223
+ - `/converse:help tools` - Tool-specific help
224
+ - `/converse:help models` - Model information
225
+ - `/converse:help parameters` - Configuration details
226
+ - `/converse:help examples` - Usage examples
227
+
228
+ ### Help Resource
229
+ Programmatic access to documentation:
230
+ - Resource URI: `converse://help`
231
+ - Includes all documentation plus current server version
232
+
132
233
  ## 📊 Supported Models
133
234
 
134
235
  ### OpenAI Models
package/bin/converse.js CHANGED
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
 
3
3
  /**
4
4
  * Converse MCP Server - CLI Entry Point
@@ -20,26 +20,13 @@ const projectRoot = dirname(__dirname);
20
20
  // Import and start the server
21
21
  try {
22
22
  const indexPath = join(projectRoot, 'src/index.js');
23
- const { startServer } = await import(pathToFileURL(indexPath).href);
23
+ const { main } = await import(pathToFileURL(indexPath).href);
24
24
 
25
- console.log('🚀 Starting Converse MCP Server...');
26
- console.log(`📁 Project root: ${projectRoot}`);
27
-
28
- await startServer();
25
+ // The main function will handle all logging appropriately based on transport type
26
+ await main();
29
27
  } catch (error) {
30
- console.error('❌ Failed to start Converse MCP Server:', error.message);
31
-
32
- if (error.code === 'ERR_MODULE_NOT_FOUND') {
33
- console.error('\n💡 Troubleshooting:');
34
- console.error(' 1. Ensure you have Node.js >= 20.0.0');
35
- console.error(' 2. Try: npm install (if running from source)');
36
- console.error(' 3. Check that all dependencies are installed');
37
- } else if (error.message.includes('API key')) {
38
- console.error('\n🔑 API Key Configuration:');
39
- console.error(' 1. Create a .env file with your API keys');
40
- console.error(' 2. Set environment variables in your MCP client');
41
- console.error(' 3. See README.md for detailed setup instructions');
42
- }
43
-
28
+ // For stdio transport, we must not output anything to stdout
29
+ // For http transport, this will be logged by the error handler in main
30
+ // Just exit with error code
44
31
  process.exit(1);
45
32
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "converse-mcp-server",
3
- "version": "1.1.1",
3
+ "version": "1.2.0",
4
4
  "description": "Converse MCP Server - Converse with other LLMs with chat and consensus tools",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
package/src/config.js CHANGED
@@ -45,25 +45,25 @@ const CONFIG_SCHEMA = {
45
45
  // Transport configuration
46
46
  transport: {
47
47
  MCP_TRANSPORT: { type: 'string', default: 'http', description: 'MCP transport type (http or stdio)' },
48
-
48
+
49
49
  // HTTP server settings
50
50
  HTTP_PORT: { type: 'number', default: 3157, description: 'HTTP server port' },
51
51
  HTTP_HOST: { type: 'string', default: 'localhost', description: 'HTTP server host' },
52
52
  HTTP_REQUEST_TIMEOUT: { type: 'number', default: 300000, description: 'HTTP request timeout in milliseconds (5 minutes)' },
53
53
  HTTP_MAX_REQUEST_SIZE: { type: 'string', default: '10mb', description: 'Maximum HTTP request body size' },
54
-
54
+
55
55
  // Session management
56
56
  HTTP_SESSION_TIMEOUT: { type: 'number', default: 1800000, description: 'Session timeout in milliseconds (30 minutes)' },
57
57
  HTTP_SESSION_CLEANUP_INTERVAL: { type: 'number', default: 300000, description: 'Session cleanup interval in milliseconds (5 minutes)' },
58
58
  HTTP_MAX_CONCURRENT_SESSIONS: { type: 'number', default: 100, description: 'Maximum concurrent sessions' },
59
-
59
+
60
60
  // CORS configuration
61
61
  HTTP_ENABLE_CORS: { type: 'boolean', default: true, description: 'Enable CORS for HTTP transport' },
62
62
  HTTP_CORS_ORIGINS: { type: 'string', default: '*', description: 'CORS allowed origins (comma-separated)' },
63
63
  HTTP_CORS_METHODS: { type: 'string', default: 'GET,POST,DELETE,OPTIONS', description: 'CORS allowed methods' },
64
64
  HTTP_CORS_HEADERS: { type: 'string', default: 'Content-Type,mcp-session-id,Authorization', description: 'CORS allowed headers' },
65
65
  HTTP_CORS_CREDENTIALS: { type: 'boolean', default: false, description: 'CORS allow credentials' },
66
-
66
+
67
67
  // Security settings
68
68
  HTTP_DNS_REBINDING_PROTECTION: { type: 'boolean', default: false, description: 'Enable DNS rebinding protection' },
69
69
  HTTP_ALLOWED_HOSTS: { type: 'string', default: '127.0.0.1,localhost', description: 'Allowed hosts for DNS rebinding protection (comma-separated)' },
@@ -163,7 +163,7 @@ function validateApiKeyFormat(provider, apiKey) {
163
163
  export async function loadConfig() {
164
164
  const configLogger = logger.operation('loadConfig');
165
165
  configLogger.debug('Starting configuration loading');
166
-
166
+
167
167
  const config = {
168
168
  server: {},
169
169
  transport: {},
@@ -193,7 +193,7 @@ export async function loadConfig() {
193
193
  for (const [key, schema] of Object.entries(CONFIG_SCHEMA.transport)) {
194
194
  try {
195
195
  const value = validateEnvVar(key, process.env[key], schema);
196
-
196
+
197
197
  if (key === 'MCP_TRANSPORT') {
198
198
  config.transport.mcptransport = value;
199
199
  } else if (key.startsWith('HTTP_')) {
@@ -286,7 +286,7 @@ export async function loadConfig() {
286
286
  */
287
287
  export function getHttpTransportConfig(config) {
288
288
  const transport = config.transport;
289
-
289
+
290
290
  // Parse comma-separated values
291
291
  const corsOrigins = transport.corsorigins === '*' ? '*' : transport.corsorigins?.split(',').map(o => o.trim()) || ['*'];
292
292
  const corsMethods = transport.corsmethods?.split(',').map(m => m.trim()) || ['GET', 'POST', 'DELETE', 'OPTIONS'];
@@ -299,12 +299,12 @@ export function getHttpTransportConfig(config) {
299
299
  host: transport.host || 'localhost',
300
300
  requestTimeout: transport.requesttimeout || 300000,
301
301
  maxRequestSize: transport.maxrequestsize || '10mb',
302
-
302
+
303
303
  // Session management
304
304
  sessionTimeout: transport.sessiontimeout || 1800000,
305
305
  sessionCleanupInterval: transport.sessioncleanupinterval || 300000,
306
306
  maxConcurrentSessions: transport.maxconcurrentsessions || 100,
307
-
307
+
308
308
  // CORS configuration
309
309
  enableCors: transport.enablecors !== false,
310
310
  corsOptions: {
@@ -314,10 +314,10 @@ export function getHttpTransportConfig(config) {
314
314
  credentials: transport.corscredentials || false,
315
315
  exposedHeaders: ['Mcp-Session-Id'],
316
316
  },
317
-
317
+
318
318
  // Security settings
319
319
  enableDnsRebindingProtection: transport.dnsrebindingprotection || false,
320
- allowedHosts: allowedHosts,
320
+ allowedHosts,
321
321
  rateLimitEnabled: transport.ratelimitenabled || false,
322
322
  rateLimitWindow: transport.ratelimitwindow || 900000,
323
323
  rateLimitMaxRequests: transport.ratelimitmaxrequests || 1000,
@@ -396,36 +396,36 @@ export async function validateRuntimeConfig(config) {
396
396
  // Validate HTTP transport configuration
397
397
  if (config.transport.mcptransport === 'http') {
398
398
  const httpConfig = getHttpTransportConfig(config);
399
-
399
+
400
400
  // Validate HTTP port
401
401
  if (httpConfig.port < 1 || httpConfig.port > 65535) {
402
402
  throw new ConfigurationError(`Invalid HTTP_PORT: ${httpConfig.port}. Must be between 1 and 65535`);
403
403
  }
404
-
404
+
405
405
  // Validate timeouts
406
406
  if (httpConfig.requestTimeout < 1000) {
407
407
  throw new ConfigurationError(`Invalid HTTP_REQUEST_TIMEOUT: ${httpConfig.requestTimeout}. Must be at least 1000ms`);
408
408
  }
409
-
409
+
410
410
  if (httpConfig.sessionTimeout < 60000) {
411
411
  throw new ConfigurationError(`Invalid HTTP_SESSION_TIMEOUT: ${httpConfig.sessionTimeout}. Must be at least 60000ms (1 minute)`);
412
412
  }
413
-
413
+
414
414
  if (httpConfig.sessionCleanupInterval < 10000) {
415
415
  throw new ConfigurationError(`Invalid HTTP_SESSION_CLEANUP_INTERVAL: ${httpConfig.sessionCleanupInterval}. Must be at least 10000ms (10 seconds)`);
416
416
  }
417
-
417
+
418
418
  // Validate max concurrent sessions
419
419
  if (httpConfig.maxConcurrentSessions < 1 || httpConfig.maxConcurrentSessions > 10000) {
420
420
  throw new ConfigurationError(`Invalid HTTP_MAX_CONCURRENT_SESSIONS: ${httpConfig.maxConcurrentSessions}. Must be between 1 and 10000`);
421
421
  }
422
-
422
+
423
423
  // Validate rate limiting
424
424
  if (httpConfig.rateLimitEnabled) {
425
425
  if (httpConfig.rateLimitWindow < 1000) {
426
426
  throw new ConfigurationError(`Invalid HTTP_RATE_LIMIT_WINDOW: ${httpConfig.rateLimitWindow}. Must be at least 1000ms`);
427
427
  }
428
-
428
+
429
429
  if (httpConfig.rateLimitMaxRequests < 1) {
430
430
  throw new ConfigurationError(`Invalid HTTP_RATE_LIMIT_MAX_REQUESTS: ${httpConfig.rateLimitMaxRequests}. Must be at least 1`);
431
431
  }
@@ -461,7 +461,7 @@ function logConfigurationSummary(config) {
461
461
  if (process.stdin.isTTY === false || process.env.NODE_ENV === 'test') {
462
462
  return;
463
463
  }
464
-
464
+
465
465
  const availableProviders = getAvailableProviders(config);
466
466
 
467
467
  // Log configuration summary
@@ -491,6 +491,8 @@ export function getMcpClientConfig(config) {
491
491
  version: config.mcp.version,
492
492
  capabilities: {
493
493
  tools: {},
494
+ prompts: {},
495
+ resources: {},
494
496
  },
495
497
  environment: config.environment.nodeEnv,
496
498
  providers: getAvailableProviders(config),
package/src/index.js CHANGED
@@ -7,6 +7,7 @@
7
7
  * with chat and consensus tools using modern Node.js practices.
8
8
  */
9
9
 
10
+ import { fileURLToPath } from 'url';
10
11
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
11
12
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
12
13
  import { loadConfig, validateRuntimeConfig, getMcpClientConfig, getHttpTransportConfig } from './config.js';
@@ -52,7 +53,7 @@ Examples:
52
53
  function getTransportType() {
53
54
  // Check command line arguments
54
55
  const args = process.argv.slice(2);
55
-
56
+
56
57
  // Support --transport=value format
57
58
  const transportEqualArg = args.find(arg => arg.startsWith('--transport='));
58
59
  if (transportEqualArg) {
@@ -61,7 +62,7 @@ function getTransportType() {
61
62
  return transport;
62
63
  }
63
64
  }
64
-
65
+
65
66
  // Support --transport value format
66
67
  const transportIndex = args.findIndex(arg => arg === '--transport');
67
68
  if (transportIndex >= 0 && transportIndex + 1 < args.length) {
@@ -93,7 +94,7 @@ async function main() {
93
94
 
94
95
  // Determine transport type first to configure logging appropriately
95
96
  const transportType = getTransportType();
96
-
97
+
97
98
  // Set environment variable early for stdio transport to suppress console output
98
99
  if (transportType === 'stdio') {
99
100
  process.env.MCP_TRANSPORT = 'stdio';
@@ -106,7 +107,7 @@ async function main() {
106
107
  }
107
108
 
108
109
  const serverTimer = startTimer('server-startup', 'server');
109
-
110
+
110
111
  try {
111
112
  logger.info('Starting Converse MCP Server');
112
113
 
@@ -116,11 +117,11 @@ async function main() {
116
117
 
117
118
  // Get MCP client configuration
118
119
  const mcpConfig = getMcpClientConfig(config);
119
-
120
+
120
121
  logger.info('Using transport type', { data: { transport: transportType } });
121
122
 
122
- logger.debug('Creating MCP server instance', {
123
- data: { name: mcpConfig.name, version: mcpConfig.version }
123
+ logger.debug('Creating MCP server instance', {
124
+ data: { name: mcpConfig.name, version: mcpConfig.version }
124
125
  });
125
126
 
126
127
  // Create MCP server with configuration
@@ -143,15 +144,15 @@ async function main() {
143
144
 
144
145
  await httpTransport.start();
145
146
  const status = httpTransport.getStatus();
146
-
147
+
147
148
  const startupTime = serverTimer('completed');
148
- logger.info('Converse MCP Server started successfully with HTTP transport', {
149
- data: {
149
+ logger.info('Converse MCP Server started successfully with HTTP transport', {
150
+ data: {
150
151
  startupTime: `${startupTime}ms`,
151
152
  endpoint: `http://${status.host}:${status.port}/mcp`,
152
153
  host: status.host,
153
154
  port: status.port
154
- }
155
+ }
155
156
  });
156
157
 
157
158
  // Store reference for shutdown
@@ -162,13 +163,13 @@ async function main() {
162
163
  await server.connect(transport);
163
164
 
164
165
  const startupTime = serverTimer('completed');
165
- logger.info('Converse MCP Server started successfully with stdio transport', {
166
- data: { startupTime: `${startupTime}ms` }
166
+ logger.info('Converse MCP Server started successfully with stdio transport', {
167
+ data: { startupTime: `${startupTime}ms` }
167
168
  });
168
169
  }
169
170
  } catch (error) {
170
171
  serverTimer('failed');
171
-
172
+
172
173
  if (error instanceof ConfigurationError) {
173
174
  logger.error('Configuration error during startup', { error });
174
175
  debugError('Configuration Error:');
@@ -190,7 +191,7 @@ async function main() {
190
191
  async function gracefulShutdown(signal) {
191
192
  logger.info(`Received ${signal}, shutting down gracefully`);
192
193
  debugError('Shutting down Converse MCP Server...');
193
-
194
+
194
195
  if (process.httpTransport) {
195
196
  try {
196
197
  await process.httpTransport.stop();
@@ -199,7 +200,7 @@ async function gracefulShutdown(signal) {
199
200
  logger.error('Error stopping HTTP transport', { error });
200
201
  }
201
202
  }
202
-
203
+
203
204
  process.exit(0);
204
205
  }
205
206
 
@@ -213,16 +214,26 @@ process.on('uncaughtException', (error) => {
213
214
  });
214
215
 
215
216
  process.on('unhandledRejection', (reason, promise) => {
216
- logger.error('Unhandled promise rejection', {
217
- error: reason,
218
- data: { promise: promise.toString() }
217
+ logger.error('Unhandled promise rejection', {
218
+ error: reason,
219
+ data: { promise: promise.toString() }
219
220
  });
220
221
  debugError('Unhandled promise rejection:', reason);
221
222
  process.exit(1);
222
223
  });
223
224
 
224
- main().catch((error) => {
225
- logger.error('Fatal error in main', { error });
226
- debugError('Fatal error:', error);
227
- process.exit(1);
228
- });
225
+ // Export the main function for use in bin/converse.js
226
+ export { main };
227
+
228
+ // Check if this module is the main entry point
229
+ // This works better across platforms and Node.js versions
230
+ const isMainModule = import.meta.url === `file://${process.argv[1].replace(/\\/g, '/')}` ||
231
+ process.argv[1] === fileURLToPath(import.meta.url);
232
+
233
+ if (isMainModule) {
234
+ main().catch((error) => {
235
+ logger.error('Fatal error in main', { error });
236
+ debugError('Fatal error:', error);
237
+ process.exit(1);
238
+ });
239
+ }