eulerian-marketing-platform 0.2.0__py3-none-any.whl → 0.2.2__py3-none-any.whl

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.
@@ -4,7 +4,7 @@ This package provides a Model Context Protocol (MCP) server that enables
4
4
  AI assistants to interact with Eulerian Marketing Platform APIs.
5
5
  """
6
6
 
7
- __version__ = "0.2.0"
7
+ __version__ = "0.2.2"
8
8
  __author__ = "Eulerian Technologies"
9
9
  __all__ = []
10
10
 
@@ -191,57 +191,90 @@ def main() -> None:
191
191
  logger.info(f"Timeout: {float(os.environ.get('EMP_TIMEOUT', '300'))}s")
192
192
  logger.info("Starting stdio proxy - all remote tools will be available")
193
193
 
194
+ # Set stdout to unbuffered mode
195
+ sys.stdout.reconfigure(line_buffering=True)
196
+
194
197
  try:
195
198
  # Read from stdin line by line
196
- for line in sys.stdin:
197
- line = line.strip()
198
- if not line:
199
- continue
200
-
199
+ while True:
201
200
  try:
202
- # Parse request
203
- request_data = json.loads(line)
201
+ line = sys.stdin.readline()
204
202
 
205
- # Forward to remote server
206
- response_data = forward_request(request_data)
203
+ # Check for EOF
204
+ if not line:
205
+ logger.info("EOF received on stdin, exiting")
206
+ break
207
207
 
208
- # Send response to stdout
209
- response_json = json.dumps(response_data)
210
- print(response_json, flush=True)
211
- logger.info(" Response forwarded [OK]")
208
+ line = line.strip()
209
+ if not line:
210
+ continue
212
211
 
213
- except json.JSONDecodeError as e:
214
- logger.error(f"ERROR: Invalid JSON in request - {e}")
215
- error_response = {
216
- "jsonrpc": "2.0",
217
- "id": None,
218
- "error": {
219
- "code": -32700,
220
- "message": f"Parse error: {str(e)}"
212
+ try:
213
+ # Parse request
214
+ request_data = json.loads(line)
215
+
216
+ # Forward to remote server
217
+ response_data = forward_request(request_data)
218
+
219
+ # Send response to stdout
220
+ response_json = json.dumps(response_data)
221
+ print(response_json, flush=True)
222
+ sys.stdout.flush() # Extra flush for safety
223
+ logger.info(" Response forwarded [OK]")
224
+
225
+ except json.JSONDecodeError as e:
226
+ logger.error(f"ERROR: Invalid JSON in request - {e}")
227
+ logger.error(f" Problematic line: {line[:200]}")
228
+ error_response = {
229
+ "jsonrpc": "2.0",
230
+ "id": None,
231
+ "error": {
232
+ "code": -32700,
233
+ "message": f"Parse error: {str(e)}"
234
+ }
221
235
  }
222
- }
223
- print(json.dumps(error_response), flush=True)
224
-
236
+ print(json.dumps(error_response), flush=True)
237
+ sys.stdout.flush()
238
+
239
+ except Exception as e:
240
+ logger.error(f"ERROR: Unexpected error processing request - {str(e)}")
241
+ import traceback
242
+ logger.error(f"Traceback: {traceback.format_exc()}")
243
+ error_response = {
244
+ "jsonrpc": "2.0",
245
+ "id": None,
246
+ "error": {
247
+ "code": -32000,
248
+ "message": f"Error: {str(e)}"
249
+ }
250
+ }
251
+ print(json.dumps(error_response), flush=True)
252
+ sys.stdout.flush()
253
+
254
+ except EOFError:
255
+ logger.info("EOF on stdin, exiting")
256
+ break
257
+ except KeyboardInterrupt:
258
+ logger.info("Server stopped by user")
259
+ break
225
260
  except Exception as e:
226
- logger.error(f"ERROR: Unexpected error processing request - {str(e)}")
261
+ logger.error(f"ERROR in main loop: {str(e)}")
227
262
  import traceback
228
263
  logger.error(f"Traceback: {traceback.format_exc()}")
229
- error_response = {
230
- "jsonrpc": "2.0",
231
- "id": None,
232
- "error": {
233
- "code": -32000,
234
- "message": f"Error: {str(e)}"
235
- }
236
- }
237
- print(json.dumps(error_response), flush=True)
264
+ # Don't break - try to continue
265
+ continue
238
266
 
239
267
  except KeyboardInterrupt:
240
268
  logger.info("Server stopped by user")
241
269
  except Exception as e:
242
270
  logger.error(f"Server error: {str(e)}")
271
+ import traceback
272
+ logger.error(f"Traceback: {traceback.format_exc()}")
243
273
  raise
274
+ finally:
275
+ logger.info("=== EULERIAN MCP PROXY SHUTDOWN ===")
244
276
 
245
277
 
246
278
  if __name__ == "__main__":
247
279
  main()
280
+
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: eulerian-marketing-platform
3
- Version: 0.2.0
3
+ Version: 0.2.2
4
4
  Summary: MCP server for Eulerian Marketing Platform - enables AI assistants to interact with Eulerian's marketing analytics and campaign management APIs
5
5
  Author-email: Eulerian Technologies <mathieu@eulerian.com>
6
6
  License: MIT
@@ -36,7 +36,7 @@ Requires-Dist: ruff (>=0.1.0) ; extra == 'dev'
36
36
 
37
37
  # Eulerian Marketing Platform MCP Server
38
38
 
39
- A Model Context Protocol (MCP) **proxy server** that bridges AI assistants (Claude Desktop, Gemini CLI, Mistral AI) to a remote Eulerian Marketing Platform MCP server. This proxy handles authentication, request forwarding, and provides a local MCP interface to your remote Eulerian instance.
39
+ A Model Context Protocol (MCP) **proxy server** that bridges AI assistants (Claude Desktop, Gemini CLI, etc ...) to a remote Eulerian Marketing Platform MCP server. This proxy handles authentication, request forwarding, and provides a local MCP interface to your remote Eulerian instance.
40
40
 
41
41
  ## How It Works
42
42
 
@@ -61,12 +61,11 @@ The proxy:
61
61
  - **🔌 Proxy Architecture**: Bridges local MCP clients to remote Eulerian MCP server via HTTP
62
62
  - **🔐 Secure Authentication**: Uses Bearer token authentication for remote server access
63
63
  - **🌐 Cross-platform support**: Works on Windows, Linux, and macOS
64
- - **🤖 Multiple AI clients**: Compatible with Claude Desktop, Gemini CLI, and Mistral AI
64
+ - **🤖 Multiple AI clients**: Compatible with Claude Desktop and Gemini CLI
65
65
  - **📝 Comprehensive Logging**: Logs all requests/responses for debugging
66
66
  - **⚡ Async HTTP**: Non-blocking requests using httpx for better performance
67
67
  - **🛠️ Tool Discovery**: Automatically discovers and exposes remote tools
68
68
  - **⏱️ Configurable Timeouts**: Adjustable request timeouts
69
- - **🔍 Easy Installation**: Deploy with a single command using `uvx`
70
69
 
71
70
  ## Prerequisites
72
71
 
@@ -76,63 +75,18 @@ The proxy:
76
75
  - One of the following AI clients:
77
76
  - Claude Desktop (Windows, macOS, Linux)
78
77
  - Gemini CLI
79
- - Mistral AI Le Chat (requires remote deployment)
80
78
 
81
79
  ## Available Tools
82
80
 
83
- The proxy exposes the following tools to AI assistants:
84
-
85
- 1. **`list_remote_tools()`** - Discover all tools available on the remote Eulerian server
86
- 2. **`call_eulerian_tool(tool_name, arguments)`** - Call any remote tool with arguments
87
- 3. **`get_eulerian_resources()`** - List available resources (data sources)
88
- 4. **`read_eulerian_resource(uri)`** - Read a specific resource by URI
89
- 5. **`get_server_info()`** - Get remote server version and capabilities
90
-
91
- For detailed information on how these tools work, see [FASTMCP_PROXY_GUIDE.md](FASTMCP_PROXY_GUIDE.md).
81
+ All API Endpoints supported by the [Eulerian API](https://doc.api.eulerian.com) can be queried through the current MCP.
92
82
 
93
83
  ## Installation
94
84
 
95
- ### Prerequisites Check
96
-
97
- Before installing, verify you have `uvx` installed. This is the recommended way to run the MCP server.
98
-
99
- **Check if uvx is installed:**
100
- ```bash
101
- uvx --version
102
- ```
103
-
104
- **If not installed, see [UVX_DEPLOYMENT_GUIDE.md](UVX_DEPLOYMENT_GUIDE.md) for detailed installation instructions.**
105
-
106
- **Quick install (Linux/macOS):**
107
- ```bash
108
- # Run the included script
109
- chmod +x install-uvx.sh
110
- ./install-uvx.sh
111
-
112
- # Or install manually
113
- curl -LsSf https://astral.sh/uv/install.sh | sh
114
- ```
115
-
116
- **Quick install (Windows PowerShell - Run as Administrator):**
117
- ```powershell
118
- # Run the included script
119
- .\install-uvx.ps1
120
-
121
- # Or install manually
122
- powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
123
- ```
124
-
125
- ---
126
-
127
85
  ### Quick Start (Recommended)
128
86
 
129
- The easiest way to use this MCP server is with `uvx`, which automatically handles dependencies without requiring a separate installation:
130
-
131
- ```bash
132
- # No installation needed! Just configure your AI client (see below)
133
- ```
87
+ The easiest way to use this MCP server is with `pip`.
134
88
 
135
- ### Alternative: Install via pip
89
+ ### Install via pip
136
90
 
137
91
  If you prefer to install the package globally:
138
92
 
@@ -153,8 +107,8 @@ pip install -e .
153
107
  ### Required Environment Variables
154
108
 
155
109
  - `EMP_API_ENDPOINT`: Your remote Eulerian Marketing Platform MCP server URL (HTTP endpoint)
156
- - Example: `https://your-eulerian-instance.com/api/mcp`
157
- - `EMP_API_TOKEN`: Your authentication token for the remote server
110
+ - Example: `https://dem.api.eulerian.com/mcp`
111
+ - `EMP_API_TOKEN`: Your authentication token for the remote server, it is the one linked to your Eulerian account.
158
112
 
159
113
  ### Optional Environment Variables
160
114
 
@@ -196,23 +150,6 @@ Claude Desktop supports local MCP servers via stdio transport.
196
150
 
197
151
  3. **Add the server configuration**:
198
152
 
199
- ```json
200
- {
201
- "mcpServers": {
202
- "eulerian-marketing-platform": {
203
- "command": "uvx",
204
- "args": ["eulerian-marketing-platform"],
205
- "env": {
206
- "EMP_API_ENDPOINT": "https://your-eulerian-instance.com/mcp",
207
- "EMP_API_TOKEN": "your_authentication_token_here"
208
- }
209
- }
210
- }
211
- }
212
- ```
213
-
214
- **Alternative: If using pip installation**:
215
-
216
153
  ```json
217
154
  {
218
155
  "mcpServers": {
@@ -243,7 +180,6 @@ Claude Desktop supports local MCP servers via stdio transport.
243
180
 
244
181
  **Linux**:
245
182
  - The config directory may not exist initially - create it with: `mkdir -p ~/.config/Claude`
246
- - Ensure `uvx` is installed: `pip install uv`
247
183
 
248
184
  **macOS**:
249
185
  - Access the config via Finder: `Cmd + Shift + G` → `~/Library/Application Support/Claude/`
@@ -284,8 +220,8 @@ nano ~/.gemini/settings.json
284
220
  {
285
221
  "mcpServers": {
286
222
  "eulerian-marketing-platform": {
287
- "command": "uvx",
288
- "args": ["eulerian-marketing-platform"],
223
+ "command": "python",
224
+ "args": ["-m", "eulerian_marketing_platform.server"],
289
225
  "env": {
290
226
  "EMP_API_ENDPOINT": "https://your-eulerian-instance.com/mcp",
291
227
  "EMP_API_TOKEN": "your_authentication_token_here"
@@ -316,102 +252,6 @@ gemini
316
252
 
317
253
  ---
318
254
 
319
- ### 3. Mistral AI (Le Chat)
320
-
321
- Mistral's Le Chat web interface supports MCP servers through **Custom Connectors**, but they must be deployed as **remote servers** with HTTP/SSE transport.
322
-
323
- #### Important Limitations
324
-
325
- - ❌ **Local stdio servers are NOT supported** by Mistral Le Chat
326
- - ✅ **Only remote HTTP/SSE servers** are supported
327
- - 📡 Your server must be publicly accessible via HTTPS
328
-
329
- #### Deployment Options
330
-
331
- You'll need to deploy your MCP server to a cloud platform. Popular options include:
332
-
333
- - **Render** (https://render.com)
334
- - **Railway** (https://railway.app)
335
- - **Fly.io** (https://fly.io)
336
- - **AWS Lambda** (with API Gateway)
337
- - **Google Cloud Run**
338
- - **Azure Container Instances**
339
-
340
- #### Server Modification for Remote Deployment
341
-
342
- Modify the `server.py` to support HTTP/SSE transport:
343
-
344
- ```python
345
- # In your server.py main() function
346
- def main() -> None:
347
- """Entry point for the MCP server."""
348
- validate_config()
349
-
350
- # For remote deployment (Mistral AI)
351
- import sys
352
- if "--remote" in sys.argv:
353
- mcp.run(transport="sse", port=8000)
354
- else:
355
- # Default stdio for local clients
356
- mcp.run()
357
- ```
358
-
359
- #### Example: Deploy to Render
360
-
361
- 1. **Create a `render.yaml` file**:
362
-
363
- ```yaml
364
- services:
365
- - type: web
366
- name: eulerian-mcp-server
367
- env: python
368
- buildCommand: pip install -e .
369
- startCommand: python -m eulerian_marketing_platform.server --remote
370
- envVars:
371
- - key: EMP_API_ENDPOINT
372
- sync: false
373
- - key: EMP_API_TOKEN
374
- sync: false
375
- ```
376
-
377
- 2. **Push to GitHub and connect to Render**
378
-
379
- 3. **Set environment variables in Render dashboard**
380
-
381
- #### Setup in Mistral Le Chat
382
-
383
- 1. **Open Le Chat** (https://chat.mistral.ai)
384
-
385
- 2. **Navigate to Connectors**:
386
- - Click the sidebar toggle
387
- - Go to `Intelligence` → `Connectors`
388
- - Click `+ Add Connector`
389
- - Select `Add custom connector`
390
-
391
- 3. **Configure the connector**:
392
- - **Name**: Eulerian Marketing Platform
393
- - **URL**: `https://your-deployed-server.render.com/mcp`
394
- - **Description**: Access to Eulerian Marketing Platform analytics and campaigns
395
- - **Authentication**:
396
- - Select `API Token Authentication` if your deployment requires it
397
- - Or `No Authentication` if your server handles auth via environment variables
398
-
399
- 4. **Connect and test**:
400
- - Click `Connect`
401
- - Once connected, enable it in a chat session
402
- - Ask: "What Eulerian Marketing Platform capabilities do you have?"
403
-
404
- #### Security Recommendations for Remote Deployment
405
-
406
- - ✅ Always use HTTPS (not HTTP)
407
- - ✅ Implement rate limiting
408
- - ✅ Add request origin validation
409
- - ✅ Use environment variables for secrets (never hardcode)
410
- - ✅ Monitor server logs for unusual activity
411
- - ✅ Consider adding IP allowlisting if possible
412
-
413
- ---
414
-
415
255
  ## Usage Examples
416
256
 
417
257
  Once configured with any client, you can interact with your remote Eulerian Marketing Platform:
@@ -420,17 +260,14 @@ Once configured with any client, you can interact with your remote Eulerian Mark
420
260
  User: "What tools are available from Eulerian?"
421
261
  → Proxy calls list_remote_tools() and returns all available tools
422
262
 
423
- User: "Call the get_campaigns tool"
424
- → Proxy forwards to remote server and returns campaign data
263
+ User: "Call the update_goal tool"
264
+ → Proxy forwards to remote server and update goal settings
425
265
 
426
266
  User: "Show me campaign details for CAMP-12345"
427
267
  → Claude uses call_eulerian_tool() to fetch specific campaign
428
268
 
429
269
  User: "What resources are available?"
430
270
  → Proxy lists all available data sources
431
-
432
- User: "Read the configuration at eulerian://config/settings"
433
- → Proxy fetches and returns the configuration
434
271
  ```
435
272
 
436
273
  The AI assistant will automatically use the appropriate proxy tools to fulfill your requests.
@@ -480,13 +317,6 @@ You'll see detailed logging of:
480
317
  - Verify the settings.json is valid JSON
481
318
  - Restart Gemini CLI
482
319
 
483
- #### Mistral connector fails to connect
484
- - **Solution**:
485
- - Verify your server is publicly accessible via `curl https://your-server.com/mcp`
486
- - Check server logs for errors
487
- - Ensure you're using HTTPS (not HTTP)
488
- - Verify the `/mcp` endpoint path is correct
489
-
490
320
  ### Debug Mode
491
321
 
492
322
  For detailed debugging:
@@ -555,9 +385,14 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file
555
385
 
556
386
  ## Changelog
557
387
 
388
+ ### 0.2.0
389
+ - Move to full Proxy mode
390
+ - Remove instructions for uvx deployment
391
+ - Remove instructions for Mistral integration (too complex)
392
+
558
393
  ### 0.1.0 (Initial Release)
559
394
  - Initial MCP server implementation
560
- - Support for Claude Desktop, Gemini CLI, and Mistral AI
395
+ - Support for Claude Desktop, Gemini CLI
561
396
  - Cross-platform support (Windows, Linux, macOS)
562
397
  - Environment-based configuration
563
398
 
@@ -0,0 +1,8 @@
1
+ eulerian_marketing_platform/__init__.py,sha256=nixrhgx4yNj_Iy4OorDr_UTciCpEXPjuJoCLngubna8,428
2
+ eulerian_marketing_platform/server.py,sha256=FnuFvs_yCIaHfDT5Q8LJb--88gZ58iUYQ7bNYYMFRYg,9710
3
+ eulerian_marketing_platform-0.2.2.dist-info/LICENSE,sha256=eIqBqE_fRsqQJ8F-2v0e-8WzZqdshsCqnzmqLAWrNHU,1078
4
+ eulerian_marketing_platform-0.2.2.dist-info/METADATA,sha256=AjQoC4KAd5cGFwGagKSUohxzzoCY9JGGJT5KUlVTxu0,12111
5
+ eulerian_marketing_platform-0.2.2.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
6
+ eulerian_marketing_platform-0.2.2.dist-info/entry_points.txt,sha256=rrPZptATSS9PUtH9gzCYq0WuP6eahkF-DkdUP1FaYfk,88
7
+ eulerian_marketing_platform-0.2.2.dist-info/top_level.txt,sha256=nidh3T6fw-mLjUqZwQ8AiMScS4usuH0WXW4ZgG4HYCo,28
8
+ eulerian_marketing_platform-0.2.2.dist-info/RECORD,,
@@ -1,8 +0,0 @@
1
- eulerian_marketing_platform/__init__.py,sha256=8Od_2veelx75AfbIEFrCS1UF6AOsKaX6CF4zR_z8yYU,428
2
- eulerian_marketing_platform/server.py,sha256=y1vy-LvSjG18dvDv65hO875s_7vogbb5bdNwTetKKcU,8335
3
- eulerian_marketing_platform-0.2.0.dist-info/LICENSE,sha256=eIqBqE_fRsqQJ8F-2v0e-8WzZqdshsCqnzmqLAWrNHU,1078
4
- eulerian_marketing_platform-0.2.0.dist-info/METADATA,sha256=B0l6BxIaS-m55cFeicvSsHEhwVKZAmwy2OaFM9eWYpY,16928
5
- eulerian_marketing_platform-0.2.0.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
6
- eulerian_marketing_platform-0.2.0.dist-info/entry_points.txt,sha256=rrPZptATSS9PUtH9gzCYq0WuP6eahkF-DkdUP1FaYfk,88
7
- eulerian_marketing_platform-0.2.0.dist-info/top_level.txt,sha256=nidh3T6fw-mLjUqZwQ8AiMScS4usuH0WXW4ZgG4HYCo,28
8
- eulerian_marketing_platform-0.2.0.dist-info/RECORD,,