cellium-mcp-client 1.0.3 → 1.1.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
@@ -1,10 +1,10 @@
1
1
  # @cellium/mcp-client
2
2
 
3
- A Model Context Protocol (MCP) client for connecting to the remote Cellium processor server via Server-Sent Events (SSE).
3
+ A Model Context Protocol (MCP) server that proxies requests to remote Cellium processor servers.
4
4
 
5
5
  ## Features
6
6
 
7
- - **SSE Transport**: Connects to remote Cellium server using Server-Sent Events
7
+ - **HTTP Proxy**: Proxies MCP requests to remote Cellium servers via HTTP
8
8
  - **Authentication**: Token-based authentication with format `user:username:hash`
9
9
  - **Robust Connection Management**: Automatic reconnection with configurable retry logic
10
10
  - **MCP Protocol Compliance**: Uses official `@modelcontextprotocol/sdk`
@@ -38,7 +38,7 @@ cellium-mcp-client --token "user:your-username:your-hash"
38
38
  # With custom endpoint and verbose logging
39
39
  cellium-mcp-client \
40
40
  --token "user:your-username:your-hash" \
41
- --endpoint "https://mcp.cellium.dev/sse" \
41
+ --endpoint "https://mcp.cellium.dev/mcp" \
42
42
  --verbose \
43
43
  --retry-attempts 5 \
44
44
  --retry-delay 2000
@@ -66,7 +66,7 @@ const logger = pino();
66
66
 
67
67
  const client = new CelliumMCPClient({
68
68
  token: 'user:your-username:your-hash',
69
- endpoint: 'https://mcp.cellium.dev/sse',
69
+ endpoint: 'https://mcp.cellium.dev/mcp',
70
70
  logger,
71
71
  retryAttempts: 3,
72
72
  retryDelay: 1000
@@ -87,7 +87,7 @@ process.on('SIGINT', async () => {
87
87
  | Option | Environment Variable | Description | Default |
88
88
  |--------|---------------------|-------------|---------|
89
89
  | `--token` | `CELLIUM_MCP_TOKEN` | Authentication token (required) | - |
90
- | `--endpoint` | - | Server endpoint URL | `https://mcp.cellium.dev/sse` |
90
+ | `--endpoint` | - | Server endpoint URL | `https://mcp.cellium.dev/mcp` |
91
91
  | `--verbose` | - | Enable verbose logging | `false` |
92
92
  | `--retry-attempts` | - | Number of retry attempts | `3` |
93
93
  | `--retry-delay` | - | Delay between retries (ms) | `1000` |
@@ -106,29 +106,20 @@ Example: `user:john-doe:a1b2c3d4e5f6...`
106
106
  ## Architecture
107
107
 
108
108
  ```
109
- ┌─────────────────┐ SSE ┌─────────────────┐
110
- │ │◄──────────►│ │
111
- MCP Client HTTPS │ Cellium Server │
112
- │ (This Package) │ (Remote) │
113
- │ │ │ │
114
- └─────────────────┘ └─────────────────┘
115
- ▲ │
116
- │ stdio │
117
- │ MCP Protocol │
118
- ▼ │
119
- ┌─────────────────┐ │
120
- │ │ │
121
- │ Code Editor / │ │
122
- │ AI Assistant │ │
123
- │ (Cody, etc.) │ │
124
- └─────────────────┘ │
109
+ ┌─────────────────┐ stdio ┌─────────────────┐ HTTPS ┌─────────────────┐
110
+ │ │◄──────────►│ │◄──────────►│
111
+ Code Editor / │ MCP cellium-mcp-HTTP │ Cellium Server │
112
+ AI Assistant │ Protocol │ client (Proxy) │ Requests │ (Remote) │
113
+ (Cody, etc.) │ │ │ │ │
114
+ └─────────────────┘ └─────────────────┘ └─────────────────┘
125
115
  ```
126
116
 
127
- The client acts as a bridge between local MCP clients (like Cody) and the remote Cellium processor server, handling:
128
- - Authentication and connection management
129
- - Protocol translation between stdio MCP and SSE
130
- - Error handling and reconnection logic
131
- - Request/response proxying
117
+ The client acts as an **MCP server proxy** between local MCP clients (like Cody) and the remote Cellium processor server, handling:
118
+ - **MCP Protocol**: Full stdio-based MCP server implementation
119
+ - **Authentication**: Token-based authentication with remote server
120
+ - **Request Proxying**: Converts MCP requests to HTTP requests to remote server
121
+ - **Error Handling**: Graceful handling of connection failures
122
+ - **Connection Management**: Automatic retry and reconnection logic
132
123
 
133
124
  ## Development
134
125
 
@@ -153,7 +144,7 @@ npm run dev
153
144
  ### Connection Issues
154
145
 
155
146
  1. **Invalid token format**: Ensure your token follows the `user:username:hash` format
156
- 2. **Network connectivity**: Check if `https://mcp.cellium.dev/sse` is accessible
147
+ 2. **Network connectivity**: Check if `https://mcp.cellium.dev/mcp` is accessible
157
148
  3. **Authentication failed**: Verify your token is valid and not expired
158
149
 
159
150
  ### Verbose Logging
package/dist/cli.js CHANGED
@@ -11,7 +11,7 @@ const program = new commander_1.Command();
11
11
  program
12
12
  .name('cellium-mcp-client')
13
13
  .description('MCP client for connecting to remote Cellium processor server')
14
- .version('1.0.3')
14
+ .version('1.1.0')
15
15
  .option('-t, --token <token>', 'Authentication token (format: user:username:hash)')
16
16
  .option('-e, --endpoint <url>', 'Server endpoint URL', 'http://localhost:3000/mcp')
17
17
  .option('-v, --verbose', 'Enable verbose logging')
package/dist/client.d.ts CHANGED
@@ -11,14 +11,12 @@ export declare class CelliumMCPClient {
11
11
  private localServer;
12
12
  private isConnected;
13
13
  private reconnectTimer?;
14
- private currentRetryCount;
15
14
  constructor(config: CelliumMCPClientConfig);
16
15
  private setupServer;
17
16
  private makeHttpRequest;
18
17
  connect(): Promise<void>;
18
+ private testConnectionInBackground;
19
19
  serve(): Promise<void>;
20
20
  private testConnection;
21
- private handleConnectionError;
22
- private reconnect;
23
21
  disconnect(): Promise<void>;
24
22
  }
package/dist/client.js CHANGED
@@ -35,7 +35,6 @@ class CelliumMCPClient {
35
35
  localServer;
36
36
  isConnected = false;
37
37
  reconnectTimer;
38
- currentRetryCount = 0;
39
38
  constructor(config) {
40
39
  this.config = {
41
40
  retryAttempts: 3,
@@ -65,47 +64,44 @@ class CelliumMCPClient {
65
64
  // Override the underlying server's tool request handlers to proxy to remote
66
65
  this.localServer.server.setRequestHandler(ToolsListSchema, async () => {
67
66
  this.config.logger.debug('Proxying tools/list to remote server');
68
- if (!this.isConnected) {
69
- throw new Error('Not connected to remote server');
70
- }
71
67
  const result = await this.makeHttpRequest('tools/list', {});
72
68
  return result;
73
69
  });
74
70
  this.localServer.server.setRequestHandler(ToolsCallSchema, async (request) => {
75
71
  this.config.logger.debug({ toolName: request.params?.name }, 'Proxying tool call to remote server');
76
- if (!this.isConnected) {
77
- throw new Error('Not connected to remote server');
78
- }
79
72
  const result = await this.makeHttpRequest('tools/call', request.params);
80
73
  return result;
81
74
  });
82
75
  // Handle resources as well
83
76
  this.localServer.server.setRequestHandler(ResourcesListSchema, async () => {
84
77
  this.config.logger.debug('Proxying resources/list to remote server');
85
- if (!this.isConnected) {
86
- throw new Error('Not connected to remote server');
87
- }
88
78
  const result = await this.makeHttpRequest('resources/list', {});
89
79
  return result;
90
80
  });
91
81
  this.localServer.server.setRequestHandler(ResourcesReadSchema, async (request) => {
92
82
  this.config.logger.debug({ uri: request.params?.uri }, 'Proxying resources/read to remote server');
93
- if (!this.isConnected) {
94
- throw new Error('Not connected to remote server');
95
- }
96
83
  const result = await this.makeHttpRequest('resources/read', request.params);
97
84
  return result;
98
85
  });
99
86
  // Handle ping
100
87
  this.localServer.server.setRequestHandler(PingSchema, async () => {
101
- if (!this.isConnected) {
102
- throw new Error('Not connected to remote server');
103
- }
104
88
  const result = await this.makeHttpRequest('ping', {});
105
89
  return result;
106
90
  });
107
91
  }
108
92
  async makeHttpRequest(method, params) {
93
+ // If not connected, try to connect first
94
+ if (!this.isConnected) {
95
+ try {
96
+ await this.testConnection();
97
+ this.isConnected = true;
98
+ this.config.logger.info('Connected to remote Cellium server');
99
+ }
100
+ catch (error) {
101
+ this.config.logger.error({ error }, 'Failed to connect to remote server');
102
+ throw new Error('Cannot connect to remote Cellium server');
103
+ }
104
+ }
109
105
  const mcpEndpoint = this.config.endpoint.replace('/sse', '/mcp');
110
106
  const requestBody = {
111
107
  jsonrpc: '2.0',
@@ -134,31 +130,38 @@ class CelliumMCPClient {
134
130
  }
135
131
  catch (error) {
136
132
  this.config.logger.error({ error, method }, 'HTTP request to remote server failed');
133
+ this.isConnected = false; // Mark as disconnected on error
137
134
  throw error;
138
135
  }
139
136
  }
140
137
  async connect() {
141
138
  try {
142
- this.config.logger.info({ endpoint: this.config.endpoint }, 'Connecting to Cellium MCP Server');
143
- // Test connection with a ping
139
+ this.config.logger.info({ endpoint: this.config.endpoint }, 'Starting Cellium MCP Server');
140
+ // Set up the stdio transport for local MCP server immediately
141
+ const stdioTransport = new stdio_js_1.StdioServerTransport();
142
+ await this.localServer.connect(stdioTransport);
143
+ this.config.logger.info('MCP Server connected and ready');
144
+ // Test connection to remote server in background, but don't block startup
145
+ this.testConnectionInBackground();
146
+ }
147
+ catch (error) {
148
+ this.config.logger.error({ error }, 'Failed to start MCP server');
149
+ throw error;
150
+ }
151
+ }
152
+ async testConnectionInBackground() {
153
+ try {
144
154
  await this.testConnection();
145
155
  this.isConnected = true;
146
- this.currentRetryCount = 0;
156
+ this.config.logger.info('Connected to remote Cellium server');
147
157
  if (this.reconnectTimer) {
148
158
  clearTimeout(this.reconnectTimer);
149
159
  this.reconnectTimer = undefined;
150
160
  }
151
- this.config.logger.info('Connected to remote Cellium server');
152
- // Set up the stdio transport for local MCP server
153
- const stdioTransport = new stdio_js_1.StdioServerTransport();
154
- await this.localServer.connect(stdioTransport);
155
- this.config.logger.info('MCP Client connected and ready');
156
161
  }
157
162
  catch (error) {
158
- this.config.logger.error({ error }, 'Failed to connect');
163
+ this.config.logger.warn({ error }, 'Failed to connect to remote server, will retry on first request');
159
164
  this.isConnected = false;
160
- this.handleConnectionError();
161
- throw error;
162
165
  }
163
166
  }
164
167
  async serve() {
@@ -192,28 +195,6 @@ class CelliumMCPClient {
192
195
  }
193
196
  this.config.logger.debug('Connection test successful');
194
197
  }
195
- handleConnectionError() {
196
- if (this.currentRetryCount < this.config.retryAttempts) {
197
- this.currentRetryCount++;
198
- this.config.logger.warn(`Connection failed, retrying in ${this.config.retryDelay}ms (attempt ${this.currentRetryCount}/${this.config.retryAttempts})`);
199
- this.reconnectTimer = setTimeout(() => {
200
- this.reconnect();
201
- }, this.config.retryDelay);
202
- }
203
- else {
204
- this.config.logger.error('Max retry attempts reached, giving up');
205
- process.exit(1);
206
- }
207
- }
208
- async reconnect() {
209
- try {
210
- await this.connect();
211
- }
212
- catch (error) {
213
- this.config.logger.error({ error }, 'Reconnection failed');
214
- this.handleConnectionError();
215
- }
216
- }
217
198
  async disconnect() {
218
199
  this.config.logger.info('Disconnecting from Cellium MCP Server');
219
200
  this.isConnected = false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cellium-mcp-client",
3
- "version": "1.0.3",
3
+ "version": "1.1.0",
4
4
  "description": "MCP client for connecting to remote Cellium processor server",
5
5
  "main": "dist/index.js",
6
6
  "bin": {