eulerian-marketing-platform 0.1.0__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.
@@ -0,0 +1,11 @@
1
+ """Eulerian Marketing Platform MCP Server.
2
+
3
+ This package provides a Model Context Protocol (MCP) server that enables
4
+ AI assistants to interact with Eulerian Marketing Platform APIs.
5
+ """
6
+
7
+ from .server import main
8
+
9
+ __version__ = "0.1.0"
10
+ __author__ = "Eulerian Technologies"
11
+ __all__ = ["main"]
@@ -0,0 +1,310 @@
1
+ #!/usr/bin/env python3
2
+ """Eulerian Marketing Platform MCP Proxy Server.
3
+
4
+ This server acts as a proxy/bridge between local MCP clients (Claude Desktop, Gemini CLI, etc.)
5
+ and a remote Eulerian Marketing Platform MCP server via HTTP.
6
+
7
+ It uses EMP_API_ENDPOINT and EMP_API_TOKEN environment variables to authenticate
8
+ and forward requests to the remote MCP server.
9
+ """
10
+
11
+ import os
12
+ import sys
13
+ import json
14
+ import logging
15
+ import tempfile
16
+ from datetime import datetime
17
+ from typing import Any
18
+ from pathlib import Path
19
+ import httpx
20
+
21
+ from mcp.server.fastmcp import FastMCP
22
+ from mcp.server import Server
23
+ from mcp.server.stdio import stdio_server
24
+ from mcp import types
25
+
26
+ # Configuration
27
+ EMP_API_ENDPOINT = os.environ.get("EMP_API_ENDPOINT")
28
+ EMP_API_TOKEN = os.environ.get("EMP_API_TOKEN")
29
+
30
+ # Logging setup - Use cross-platform temp directory
31
+ # Default to system temp directory if EMP_LOG_FILE not set
32
+ DEFAULT_LOG_FILE = os.path.join(tempfile.gettempdir(), "eulerian-mcp-proxy.log")
33
+ LOG_FILE = os.environ.get("EMP_LOG_FILE", DEFAULT_LOG_FILE)
34
+
35
+ # Ensure log directory exists
36
+ log_dir = os.path.dirname(LOG_FILE)
37
+ if log_dir: # Only create if there's a directory part
38
+ os.makedirs(log_dir, exist_ok=True)
39
+
40
+ # Configure logging to file and stderr
41
+ logging.basicConfig(
42
+ level=logging.INFO,
43
+ format="[%(asctime)s] %(levelname)s: %(message)s",
44
+ datefmt="%Y-%m-%d %H:%M:%S",
45
+ handlers=[
46
+ logging.FileHandler(LOG_FILE),
47
+ logging.StreamHandler(sys.stderr)
48
+ ]
49
+ )
50
+ logger = logging.getLogger(__name__)
51
+
52
+
53
+ def validate_config() -> None:
54
+ """Validate that required environment variables are set."""
55
+ missing_vars = []
56
+
57
+ if not EMP_API_ENDPOINT:
58
+ missing_vars.append("EMP_API_ENDPOINT")
59
+ if not EMP_API_TOKEN:
60
+ missing_vars.append("EMP_API_TOKEN")
61
+
62
+ if missing_vars:
63
+ logger.error("The following required environment variables are missing:")
64
+ for var in missing_vars:
65
+ logger.error(f" - {var}")
66
+ logger.error("\nPlease set these environment variables before running the server.")
67
+ logger.error("Example:")
68
+ logger.error(" export EMP_API_ENDPOINT=https://your-eulerian-instance.com/api/mcp")
69
+ logger.error(" export EMP_API_TOKEN=your_authentication_token")
70
+ sys.exit(1)
71
+
72
+
73
+ class EulerianMCPProxy:
74
+ """Proxy that forwards MCP requests to remote Eulerian server."""
75
+
76
+ def __init__(self):
77
+ """Initialize the proxy with configuration."""
78
+ self.endpoint = EMP_API_ENDPOINT
79
+ self.token = EMP_API_TOKEN
80
+ self.timeout = float(os.environ.get("EMP_TIMEOUT", "300"))
81
+
82
+ logger.info("=== EULERIAN MCP PROXY START ===")
83
+ logger.info(f"Endpoint: {self.endpoint}")
84
+ logger.info(f"Token: {self.token[:10] if self.token else 'None'}...")
85
+ logger.info(f"Timeout: {self.timeout}s")
86
+
87
+ async def forward_request(self, method: str, params: dict = None) -> dict[str, Any]:
88
+ """Forward a JSON-RPC request to the remote MCP server.
89
+
90
+ Args:
91
+ method: The JSON-RPC method name
92
+ params: The parameters for the method
93
+
94
+ Returns:
95
+ The response from the remote server
96
+
97
+ Raises:
98
+ Exception: If the request fails
99
+ """
100
+ request_data = {
101
+ "jsonrpc": "2.0",
102
+ "id": 1,
103
+ "method": method,
104
+ }
105
+ if params:
106
+ request_data["params"] = params
107
+
108
+ logger.info(f">>> REQUEST: {method}")
109
+ logger.debug(f" Full request: {json.dumps(request_data)[:200]}...")
110
+
111
+ try:
112
+ async with httpx.AsyncClient() as client:
113
+ logger.info(f"Forwarding to {self.endpoint}")
114
+ response = await client.post(
115
+ self.endpoint,
116
+ headers={
117
+ "Content-Type": "application/json",
118
+ "Authorization": f"Bearer {self.token}"
119
+ },
120
+ json=request_data,
121
+ timeout=self.timeout
122
+ )
123
+
124
+ logger.info(f"<<< RESPONSE: HTTP {response.status_code}")
125
+
126
+ if response.status_code != 200:
127
+ error_msg = f"HTTP {response.status_code}: {response.reason_phrase}"
128
+ logger.error(f" Error: {response.text[:200]}")
129
+ raise Exception(error_msg)
130
+
131
+ response_data = response.json()
132
+ logger.debug(f" Response: {json.dumps(response_data)[:200]}...")
133
+
134
+ # Validate JSON-RPC response
135
+ if "jsonrpc" not in response_data:
136
+ logger.warning(" WARNING: Missing 'jsonrpc' field")
137
+
138
+ if "result" in response_data:
139
+ logger.info(" Has 'result' field [OK]")
140
+ return response_data["result"]
141
+ elif "error" in response_data:
142
+ logger.error(f" Has 'error' field: {response_data['error']}")
143
+ raise Exception(f"Remote error: {response_data['error']}")
144
+ else:
145
+ logger.warning(" No 'result' or 'error' field")
146
+ return response_data
147
+
148
+ except httpx.TimeoutException:
149
+ logger.error("ERROR: Request timeout")
150
+ raise Exception("Request timeout")
151
+ except httpx.RequestError as e:
152
+ logger.error(f"ERROR: Request failed - {str(e)}")
153
+ raise Exception(f"Request failed: {str(e)}")
154
+ except json.JSONDecodeError as e:
155
+ logger.error(f"ERROR: Invalid JSON response - {str(e)}")
156
+ raise Exception(f"Invalid JSON response: {str(e)}")
157
+
158
+
159
+ # Create global proxy instance
160
+ proxy = EulerianMCPProxy()
161
+
162
+ # Create FastMCP server
163
+ mcp = FastMCP("eulerian-marketing-platform")
164
+
165
+
166
+ # Dynamically fetch and register tools from remote server
167
+ @mcp.tool()
168
+ async def list_remote_tools() -> dict[str, Any]:
169
+ """List all available tools from the remote Eulerian MCP server.
170
+
171
+ This tool queries the remote MCP server to discover what tools are available.
172
+ Use this to see what operations you can perform on the Eulerian platform.
173
+
174
+ Returns:
175
+ Dictionary containing the list of available tools with their descriptions
176
+ """
177
+ try:
178
+ result = await proxy.forward_request("tools/list")
179
+ return result
180
+ except Exception as e:
181
+ logger.error(f"Failed to list tools: {str(e)}")
182
+ return {"error": str(e), "tools": []}
183
+
184
+
185
+ @mcp.tool()
186
+ async def call_eulerian_tool(tool_name: str, arguments: dict[str, Any] = None) -> dict[str, Any]:
187
+ """Call a tool on the remote Eulerian MCP server.
188
+
189
+ This is a generic tool that forwards requests to the remote Eulerian platform.
190
+ First use list_remote_tools() to see what tools are available, then call them
191
+ using this function.
192
+
193
+ Args:
194
+ tool_name: The name of the tool to call on the remote server
195
+ arguments: Dictionary of arguments to pass to the tool (optional)
196
+
197
+ Returns:
198
+ The result from the remote tool execution
199
+
200
+ Example:
201
+ To call a tool named "search_goal" with no arguments:
202
+ >>> call_eulerian_tool("search_goal")
203
+
204
+ To call a tool with arguments:
205
+ >>> call_eulerian_tool("update_goal", {"action-id": "12345","action-name":"test-mcp"})
206
+ """
207
+ if arguments is None:
208
+ arguments = {}
209
+
210
+ try:
211
+ params = {
212
+ "name": tool_name,
213
+ "arguments": arguments
214
+ }
215
+ result = await proxy.forward_request("tools/call", params)
216
+ return result
217
+ except Exception as e:
218
+ logger.error(f"Failed to call tool '{tool_name}': {str(e)}")
219
+ return {"error": str(e), "tool": tool_name}
220
+
221
+
222
+ @mcp.tool()
223
+ async def get_eulerian_resources() -> dict[str, Any]:
224
+ """List all available resources from the remote Eulerian MCP server.
225
+
226
+ Resources are data sources that can be read from the Eulerian platform,
227
+ such as configuration files, reports, or reference data.
228
+
229
+ Returns:
230
+ Dictionary containing the list of available resources
231
+ """
232
+ try:
233
+ result = await proxy.forward_request("resources/list")
234
+ return result
235
+ except Exception as e:
236
+ logger.error(f"Failed to list resources: {str(e)}")
237
+ return {"error": str(e), "resources": []}
238
+
239
+
240
+ @mcp.tool()
241
+ async def read_eulerian_resource(uri: str) -> dict[str, Any]:
242
+ """Read a specific resource from the remote Eulerian MCP server.
243
+
244
+ Args:
245
+ uri: The URI of the resource to read (get from get_eulerian_resources())
246
+
247
+ Returns:
248
+ The content of the requested resource
249
+
250
+ Example:
251
+ >>> read_eulerian_resource("eulerian://config/settings")
252
+ """
253
+ try:
254
+ params = {"uri": uri}
255
+ result = await proxy.forward_request("resources/read", params)
256
+ return result
257
+ except Exception as e:
258
+ logger.error(f"Failed to read resource '{uri}': {str(e)}")
259
+ return {"error": str(e), "uri": uri}
260
+
261
+
262
+ @mcp.tool()
263
+ async def get_server_info() -> dict[str, Any]:
264
+ """Get information about the remote Eulerian MCP server.
265
+
266
+ Returns server capabilities, version, and other metadata.
267
+
268
+ Returns:
269
+ Dictionary containing server information
270
+ """
271
+ try:
272
+ result = await proxy.forward_request("initialize", {
273
+ "protocolVersion": "2024-11-05",
274
+ "capabilities": {},
275
+ "clientInfo": {
276
+ "name": "eulerian-mcp-proxy",
277
+ "version": "0.1.0"
278
+ }
279
+ })
280
+ return result
281
+ except Exception as e:
282
+ logger.error(f"Failed to get server info: {str(e)}")
283
+ return {"error": str(e)}
284
+
285
+
286
+ def main() -> None:
287
+ """Entry point for the MCP proxy server."""
288
+ # Validate configuration before starting
289
+ validate_config()
290
+
291
+ logger.info("Starting Eulerian MCP Proxy Server...")
292
+ logger.info("Available tools:")
293
+ logger.info(" - list_remote_tools: List all tools from remote server")
294
+ logger.info(" - call_eulerian_tool: Call any remote tool")
295
+ logger.info(" - get_eulerian_resources: List available resources")
296
+ logger.info(" - read_eulerian_resource: Read a specific resource")
297
+ logger.info(" - get_server_info: Get remote server information")
298
+
299
+ # Run the server in stdio mode (default for MCP)
300
+ try:
301
+ mcp.run()
302
+ except KeyboardInterrupt:
303
+ logger.info("Server stopped by user")
304
+ except Exception as e:
305
+ logger.error(f"Server error: {str(e)}")
306
+ raise
307
+
308
+
309
+ if __name__ == "__main__":
310
+ main()
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Eulerian Technologies
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,567 @@
1
+ Metadata-Version: 2.1
2
+ Name: eulerian-marketing-platform
3
+ Version: 0.1.0
4
+ Summary: MCP server for Eulerian Marketing Platform - enables AI assistants to interact with Eulerian's marketing analytics and campaign management APIs
5
+ Author-email: Eulerian Technologies <mathieu@eulerian.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/EulerianTechnologies/eulerian-marketing-platform-mcp
8
+ Project-URL: Issues, https://github.com/EulerianTechnologies/eulerian-marketing-platform-mcp/issues
9
+ Project-URL: Documentation, https://github.com/EulerianTechnologies/eulerian-marketing-platform-mcp#readme
10
+ Project-URL: Repository, https://github.com/EulerianTechnologies/eulerian-marketing-platform-mcp
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Operating System :: Microsoft :: Windows
16
+ Classifier: Operating System :: POSIX :: Linux
17
+ Classifier: Operating System :: MacOS
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
23
+ Requires-Python: >=3.10
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Requires-Dist: httpx (>=0.25.0)
27
+ Requires-Dist: mcp (>=1.2.0)
28
+ Provides-Extra: deployment
29
+ Requires-Dist: uv (>=0.5.0) ; extra == 'deployment'
30
+ Provides-Extra: dev
31
+ Requires-Dist: black (>=23.0.0) ; extra == 'dev'
32
+ Requires-Dist: mypy (>=1.0.0) ; extra == 'dev'
33
+ Requires-Dist: pytest-asyncio (>=0.21.0) ; extra == 'dev'
34
+ Requires-Dist: pytest-cov (>=4.0.0) ; extra == 'dev'
35
+ Requires-Dist: pytest (>=7.0.0) ; extra == 'dev'
36
+ Requires-Dist: ruff (>=0.1.0) ; extra == 'dev'
37
+
38
+ # Eulerian Marketing Platform MCP Server
39
+
40
+ 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.
41
+
42
+ ## How It Works
43
+
44
+ This server acts as a **transparent proxy** between local MCP clients and your remote Eulerian Marketing Platform server:
45
+
46
+ ```
47
+ ┌─────────────┐ ┌──────────────────┐ ┌────────────────┐
48
+ │ Claude │ ◄─────►│ This MCP Proxy │◄─────► │ Remote Eulerian│
49
+ │ Desktop │ stdio │ (Local) │ HTTP │ MCP Server │
50
+ └─────────────┘ └──────────────────┘ └────────────────┘
51
+ ```
52
+
53
+ The proxy:
54
+ - 🔐 Handles authentication with your remote Eulerian server
55
+ - 📡 Forwards MCP requests via HTTP with Bearer token
56
+ - 🛠️ Exposes remote tools and resources to AI assistants
57
+ - 📝 Provides comprehensive logging for debugging
58
+ - ⚡ Uses async HTTP for better performance
59
+
60
+ ## Features
61
+
62
+ - **🔌 Proxy Architecture**: Bridges local MCP clients to remote Eulerian MCP server via HTTP
63
+ - **🔐 Secure Authentication**: Uses Bearer token authentication for remote server access
64
+ - **🌐 Cross-platform support**: Works on Windows, Linux, and macOS
65
+ - **🤖 Multiple AI clients**: Compatible with Claude Desktop, Gemini CLI, and Mistral AI
66
+ - **📝 Comprehensive Logging**: Logs all requests/responses for debugging
67
+ - **⚡ Async HTTP**: Non-blocking requests using httpx for better performance
68
+ - **🛠️ Tool Discovery**: Automatically discovers and exposes remote tools
69
+ - **⏱️ Configurable Timeouts**: Adjustable request timeouts
70
+ - **🔍 Easy Installation**: Deploy with a single command using `uvx`
71
+
72
+ ## Prerequisites
73
+
74
+ - Python 3.10 or higher
75
+ - Access to a remote Eulerian Marketing Platform MCP server (HTTP endpoint)
76
+ - Valid authentication token for the remote server
77
+ - One of the following AI clients:
78
+ - Claude Desktop (Windows, macOS, Linux)
79
+ - Gemini CLI
80
+ - Mistral AI Le Chat (requires remote deployment)
81
+
82
+ ## Available Tools
83
+
84
+ The proxy exposes the following tools to AI assistants:
85
+
86
+ 1. **`list_remote_tools()`** - Discover all tools available on the remote Eulerian server
87
+ 2. **`call_eulerian_tool(tool_name, arguments)`** - Call any remote tool with arguments
88
+ 3. **`get_eulerian_resources()`** - List available resources (data sources)
89
+ 4. **`read_eulerian_resource(uri)`** - Read a specific resource by URI
90
+ 5. **`get_server_info()`** - Get remote server version and capabilities
91
+
92
+ For detailed information on how these tools work, see [FASTMCP_PROXY_GUIDE.md](FASTMCP_PROXY_GUIDE.md).
93
+
94
+ ## Installation
95
+
96
+ ### Prerequisites Check
97
+
98
+ Before installing, verify you have `uvx` installed. This is the recommended way to run the MCP server.
99
+
100
+ **Check if uvx is installed:**
101
+ ```bash
102
+ uvx --version
103
+ ```
104
+
105
+ **If not installed, see [UVX_DEPLOYMENT_GUIDE.md](UVX_DEPLOYMENT_GUIDE.md) for detailed installation instructions.**
106
+
107
+ **Quick install (Linux/macOS):**
108
+ ```bash
109
+ # Run the included script
110
+ chmod +x install-uvx.sh
111
+ ./install-uvx.sh
112
+
113
+ # Or install manually
114
+ curl -LsSf https://astral.sh/uv/install.sh | sh
115
+ ```
116
+
117
+ **Quick install (Windows PowerShell - Run as Administrator):**
118
+ ```powershell
119
+ # Run the included script
120
+ .\install-uvx.ps1
121
+
122
+ # Or install manually
123
+ powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
124
+ ```
125
+
126
+ ---
127
+
128
+ ### Quick Start (Recommended)
129
+
130
+ The easiest way to use this MCP server is with `uvx`, which automatically handles dependencies without requiring a separate installation:
131
+
132
+ ```bash
133
+ # No installation needed! Just configure your AI client (see below)
134
+ ```
135
+
136
+ ### Alternative: Install via pip
137
+
138
+ If you prefer to install the package globally:
139
+
140
+ ```bash
141
+ pip install eulerian-marketing-platform
142
+ ```
143
+
144
+ ### Alternative: Install from source
145
+
146
+ ```bash
147
+ git clone https://github.com/EulerianTechnologies/eulerian-marketing-platform-mcp.git
148
+ cd eulerian-marketing-platform-mcp
149
+ pip install -e .
150
+ ```
151
+
152
+ ## Configuration
153
+
154
+ ### Required Environment Variables
155
+
156
+ - `EMP_API_ENDPOINT`: Your remote Eulerian Marketing Platform MCP server URL (HTTP endpoint)
157
+ - Example: `https://your-eulerian-instance.com/api/mcp`
158
+ - `EMP_API_TOKEN`: Your authentication token for the remote server
159
+
160
+ ### Optional Environment Variables
161
+
162
+ - `EMP_LOG_FILE`: Log file location (default: `/tmp/eulerian-mcp-proxy.log`)
163
+ - `EMP_TIMEOUT`: Request timeout in seconds (default: `300`)
164
+
165
+ ### Example `.env` file
166
+
167
+ Create a `.env.example` file in your project:
168
+
169
+ ```bash
170
+ # Required
171
+ EMP_API_ENDPOINT=https://your-eulerian-instance.com/mcp
172
+ EMP_API_TOKEN=your_authentication_token_here
173
+
174
+ # Optional
175
+ EMP_LOG_FILE=/var/log/eulerian-mcp-proxy.log
176
+ EMP_TIMEOUT=600
177
+ ```
178
+
179
+ ## Setup Instructions by Client
180
+
181
+ ### 1. Claude Desktop
182
+
183
+ Claude Desktop supports local MCP servers via stdio transport.
184
+
185
+ #### Configuration File Locations
186
+
187
+ - **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
188
+ - **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
189
+ - **Linux**: `~/.config/Claude/claude_desktop_config.json`
190
+
191
+ #### Setup Steps
192
+
193
+ 1. **Open Claude Desktop**
194
+ 2. **Access configuration**:
195
+ - Click `Claude` menu → `Settings` → `Developer` → `Edit Config`
196
+ - Or manually edit the JSON file at the location above
197
+
198
+ 3. **Add the server configuration**:
199
+
200
+ ```json
201
+ {
202
+ "mcpServers": {
203
+ "eulerian-marketing-platform": {
204
+ "command": "uvx",
205
+ "args": ["eulerian-marketing-platform"],
206
+ "env": {
207
+ "EMP_API_ENDPOINT": "https://your-eulerian-instance.com/mcp",
208
+ "EMP_API_TOKEN": "your_authentication_token_here"
209
+ }
210
+ }
211
+ }
212
+ }
213
+ ```
214
+
215
+ **Alternative: If using pip installation**:
216
+
217
+ ```json
218
+ {
219
+ "mcpServers": {
220
+ "eulerian-marketing-platform": {
221
+ "command": "python",
222
+ "args": ["-m", "eulerian_marketing_platform.server"],
223
+ "env": {
224
+ "EMP_API_ENDPOINT": "https://your-eulerian-instance.com/mcp",
225
+ "EMP_API_TOKEN": "your_authentication_token_here"
226
+ }
227
+ }
228
+ }
229
+ }
230
+ ```
231
+
232
+ 4. **Restart Claude Desktop**
233
+
234
+ 5. **Verify the connection**:
235
+ - Look for a hammer/tools icon (🔨) in the bottom-right corner
236
+ - Click it to see available Eulerian tools
237
+ - Ask Claude: "What Eulerian Marketing Platform tools do you have access to?"
238
+
239
+ #### Platform-Specific Notes
240
+
241
+ **Windows**:
242
+ - Use the Run dialog (`Win + R`) and enter `%APPDATA%\Claude` to quickly navigate to the config directory
243
+ - If using a local installation, ensure Python is in your PATH
244
+
245
+ **Linux**:
246
+ - The config directory may not exist initially - create it with: `mkdir -p ~/.config/Claude`
247
+ - Ensure `uvx` is installed: `pip install uv`
248
+
249
+ **macOS**:
250
+ - Access the config via Finder: `Cmd + Shift + G` → `~/Library/Application Support/Claude/`
251
+
252
+ ---
253
+
254
+ ### 2. Gemini CLI
255
+
256
+ Gemini CLI supports MCP servers through its configuration file.
257
+
258
+ #### Prerequisites
259
+
260
+ Install Gemini CLI if you haven't already:
261
+
262
+ ```bash
263
+ npm install -g @google/gemini-cli
264
+ ```
265
+
266
+ #### Configuration File Location
267
+
268
+ `~/.gemini/settings.json`
269
+
270
+ #### Setup Steps
271
+
272
+ 1. **Create or edit the settings file**:
273
+
274
+ ```bash
275
+ # Create the directory if it doesn't exist
276
+ mkdir -p ~/.gemini
277
+
278
+ # Edit the settings file
279
+ nano ~/.gemini/settings.json
280
+ ```
281
+
282
+ 2. **Add the MCP server configuration**:
283
+
284
+ ```json
285
+ {
286
+ "mcpServers": {
287
+ "eulerian-marketing-platform": {
288
+ "command": "uvx",
289
+ "args": ["eulerian-marketing-platform"],
290
+ "env": {
291
+ "EMP_API_ENDPOINT": "https://your-eulerian-instance.com/mcp",
292
+ "EMP_API_TOKEN": "your_authentication_token_here"
293
+ }
294
+ }
295
+ }
296
+ }
297
+ ```
298
+
299
+ 3. **Start Gemini CLI**:
300
+
301
+ ```bash
302
+ gemini
303
+ ```
304
+
305
+ 4. **Verify the connection**:
306
+ - Use the `/mcp` command to see connected servers
307
+ - Ask Gemini: "What tools are available from the Eulerian Marketing Platform?"
308
+
309
+ #### Platform-Specific Notes
310
+
311
+ **Windows**:
312
+ - Settings file location: `%USERPROFILE%\.gemini\settings.json`
313
+ - Create directory: `mkdir %USERPROFILE%\.gemini`
314
+
315
+ **Linux/macOS**:
316
+ - Standard location: `~/.gemini/settings.json`
317
+
318
+ ---
319
+
320
+ ### 3. Mistral AI (Le Chat)
321
+
322
+ Mistral's Le Chat web interface supports MCP servers through **Custom Connectors**, but they must be deployed as **remote servers** with HTTP/SSE transport.
323
+
324
+ #### Important Limitations
325
+
326
+ - ❌ **Local stdio servers are NOT supported** by Mistral Le Chat
327
+ - ✅ **Only remote HTTP/SSE servers** are supported
328
+ - 📡 Your server must be publicly accessible via HTTPS
329
+
330
+ #### Deployment Options
331
+
332
+ You'll need to deploy your MCP server to a cloud platform. Popular options include:
333
+
334
+ - **Render** (https://render.com)
335
+ - **Railway** (https://railway.app)
336
+ - **Fly.io** (https://fly.io)
337
+ - **AWS Lambda** (with API Gateway)
338
+ - **Google Cloud Run**
339
+ - **Azure Container Instances**
340
+
341
+ #### Server Modification for Remote Deployment
342
+
343
+ Modify the `server.py` to support HTTP/SSE transport:
344
+
345
+ ```python
346
+ # In your server.py main() function
347
+ def main() -> None:
348
+ """Entry point for the MCP server."""
349
+ validate_config()
350
+
351
+ # For remote deployment (Mistral AI)
352
+ import sys
353
+ if "--remote" in sys.argv:
354
+ mcp.run(transport="sse", port=8000)
355
+ else:
356
+ # Default stdio for local clients
357
+ mcp.run()
358
+ ```
359
+
360
+ #### Example: Deploy to Render
361
+
362
+ 1. **Create a `render.yaml` file**:
363
+
364
+ ```yaml
365
+ services:
366
+ - type: web
367
+ name: eulerian-mcp-server
368
+ env: python
369
+ buildCommand: pip install -e .
370
+ startCommand: python -m eulerian_marketing_platform.server --remote
371
+ envVars:
372
+ - key: EMP_API_ENDPOINT
373
+ sync: false
374
+ - key: EMP_API_TOKEN
375
+ sync: false
376
+ ```
377
+
378
+ 2. **Push to GitHub and connect to Render**
379
+
380
+ 3. **Set environment variables in Render dashboard**
381
+
382
+ #### Setup in Mistral Le Chat
383
+
384
+ 1. **Open Le Chat** (https://chat.mistral.ai)
385
+
386
+ 2. **Navigate to Connectors**:
387
+ - Click the sidebar toggle
388
+ - Go to `Intelligence` → `Connectors`
389
+ - Click `+ Add Connector`
390
+ - Select `Add custom connector`
391
+
392
+ 3. **Configure the connector**:
393
+ - **Name**: Eulerian Marketing Platform
394
+ - **URL**: `https://your-deployed-server.render.com/mcp`
395
+ - **Description**: Access to Eulerian Marketing Platform analytics and campaigns
396
+ - **Authentication**:
397
+ - Select `API Token Authentication` if your deployment requires it
398
+ - Or `No Authentication` if your server handles auth via environment variables
399
+
400
+ 4. **Connect and test**:
401
+ - Click `Connect`
402
+ - Once connected, enable it in a chat session
403
+ - Ask: "What Eulerian Marketing Platform capabilities do you have?"
404
+
405
+ #### Security Recommendations for Remote Deployment
406
+
407
+ - ✅ Always use HTTPS (not HTTP)
408
+ - ✅ Implement rate limiting
409
+ - ✅ Add request origin validation
410
+ - ✅ Use environment variables for secrets (never hardcode)
411
+ - ✅ Monitor server logs for unusual activity
412
+ - ✅ Consider adding IP allowlisting if possible
413
+
414
+ ---
415
+
416
+ ## Usage Examples
417
+
418
+ Once configured with any client, you can interact with your remote Eulerian Marketing Platform:
419
+
420
+ ```
421
+ User: "What tools are available from Eulerian?"
422
+ → Proxy calls list_remote_tools() and returns all available tools
423
+
424
+ User: "Call the get_campaigns tool"
425
+ → Proxy forwards to remote server and returns campaign data
426
+
427
+ User: "Show me campaign details for CAMP-12345"
428
+ → Claude uses call_eulerian_tool() to fetch specific campaign
429
+
430
+ User: "What resources are available?"
431
+ → Proxy lists all available data sources
432
+
433
+ User: "Read the configuration at eulerian://config/settings"
434
+ → Proxy fetches and returns the configuration
435
+ ```
436
+
437
+ The AI assistant will automatically use the appropriate proxy tools to fulfill your requests.
438
+
439
+ ### Viewing Logs
440
+
441
+ Monitor proxy activity in real-time:
442
+
443
+ ```bash
444
+ # Default log location
445
+ tail -f /tmp/eulerian-mcp-proxy.log
446
+
447
+ # Custom log location
448
+ tail -f /var/log/eulerian-mcp-proxy.log
449
+ ```
450
+
451
+ You'll see detailed logging of:
452
+ - Requests to the remote server
453
+ - HTTP responses and status codes
454
+ - Tool calls and results
455
+ - Errors and warnings
456
+
457
+ ## Troubleshooting
458
+
459
+ ### Common Issues
460
+
461
+ #### "EMP_API_ENDPOINT environment variable is required"
462
+ - **Solution**: Ensure you've set the `EMP_API_ENDPOINT` in your configuration
463
+ - Check that there are no typos in the environment variable name
464
+
465
+ #### "EMP_API_TOKEN environment variable is required"
466
+ - **Solution**: Ensure you've set the `EMP_API_TOKEN` in your configuration
467
+ - Verify your token is valid and hasn't expired
468
+
469
+ #### Server not appearing in Claude Desktop
470
+ - **Solution**:
471
+ - Restart Claude Desktop completely
472
+ - Check the configuration file for JSON syntax errors
473
+ - Verify the file path in your config is correct
474
+ - Look at logs:
475
+ - macOS: `~/Library/Logs/Claude/mcp-server-*.log`
476
+ - Windows: `%APPDATA%\Claude\logs\`
477
+
478
+ #### Tools not showing in Gemini CLI
479
+ - **Solution**:
480
+ - Use `/mcp` command to check server status
481
+ - Verify the settings.json is valid JSON
482
+ - Restart Gemini CLI
483
+
484
+ #### Mistral connector fails to connect
485
+ - **Solution**:
486
+ - Verify your server is publicly accessible via `curl https://your-server.com/mcp`
487
+ - Check server logs for errors
488
+ - Ensure you're using HTTPS (not HTTP)
489
+ - Verify the `/mcp` endpoint path is correct
490
+
491
+ ### Debug Mode
492
+
493
+ For detailed debugging:
494
+
495
+ ```bash
496
+ # Run with MCP Inspector
497
+ npx @modelcontextprotocol/inspector uvx eulerian-marketing-platform
498
+
499
+ # Or with environment variables
500
+ EMP_API_ENDPOINT=your_endpoint EMP_API_TOKEN=your_token uvx eulerian-marketing-platform
501
+ ```
502
+
503
+ ## Development
504
+
505
+ ### Running Tests
506
+
507
+ ```bash
508
+ # Install development dependencies
509
+ pip install -e ".[dev]"
510
+
511
+ # Run tests
512
+ pytest
513
+
514
+ # Run with coverage
515
+ pytest --cov=eulerian_marketing_platform
516
+ ```
517
+
518
+ ### Building from Source
519
+
520
+ ```bash
521
+ # Clone the repository
522
+ git clone https://github.com/EulerianTechnologies/eulerian-marketing-platform-mcp.git
523
+ cd eulerian-marketing-platform-mcp
524
+
525
+ # Install in development mode
526
+ pip install -e .
527
+
528
+ # Build distribution
529
+ pip install build
530
+ python -m build
531
+
532
+ # This creates:
533
+ # dist/eulerian_marketing_platform-0.1.0.tar.gz
534
+ # dist/eulerian_marketing_platform-0.1.0-py3-none-any.whl
535
+ ```
536
+
537
+ ## Contributing
538
+
539
+ Contributions are welcome! Please feel free to submit a Pull Request.
540
+
541
+ 1. Fork the repository
542
+ 2. Create your feature branch (`git checkout -b feature/amazing-feature`)
543
+ 3. Commit your changes (`git commit -m 'Add amazing feature'`)
544
+ 4. Push to the branch (`git push origin feature/amazing-feature`)
545
+ 5. Open a Pull Request
546
+
547
+ ## License
548
+
549
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
550
+
551
+ ## Support
552
+
553
+ - **Issues**: https://github.com/EulerianTechnologies/eulerian-marketing-platform-mcp/issues
554
+ - **Documentation**: https://github.com/EulerianTechnologies/eulerian-marketing-platform-mcp#readme
555
+ - **Eulerian Technologies**: https://www.eulerian.com
556
+
557
+ ## Changelog
558
+
559
+ ### 0.1.0 (Initial Release)
560
+ - Initial MCP server implementation
561
+ - Support for Claude Desktop, Gemini CLI, and Mistral AI
562
+ - Cross-platform support (Windows, Linux, macOS)
563
+ - Environment-based configuration
564
+
565
+ ---
566
+
567
+ **Note**: Replace all placeholder URLs and tokens with your actual Eulerian Marketing Platform credentials before use.
@@ -0,0 +1,8 @@
1
+ eulerian_marketing_platform/__init__.py,sha256=1SFZ-y65v1oNQblA2aAEF8zwN8p1UjfRowWDpDx6Hxo,291
2
+ eulerian_marketing_platform/server.py,sha256=R7qW5Fclv1sbcFEN5L4Upe6c-BwXsod6Q16Tuyxgc9c,10712
3
+ eulerian_marketing_platform-0.1.0.dist-info/LICENSE,sha256=eIqBqE_fRsqQJ8F-2v0e-8WzZqdshsCqnzmqLAWrNHU,1078
4
+ eulerian_marketing_platform-0.1.0.dist-info/METADATA,sha256=nInhhh00c6jUOQm3cRchWTS9jhAWS5D4T5CkMLCTtg8,16957
5
+ eulerian_marketing_platform-0.1.0.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
6
+ eulerian_marketing_platform-0.1.0.dist-info/entry_points.txt,sha256=rrPZptATSS9PUtH9gzCYq0WuP6eahkF-DkdUP1FaYfk,88
7
+ eulerian_marketing_platform-0.1.0.dist-info/top_level.txt,sha256=nidh3T6fw-mLjUqZwQ8AiMScS4usuH0WXW4ZgG4HYCo,28
8
+ eulerian_marketing_platform-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: bdist_wheel (0.38.4)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ eulerian-marketing-platform = eulerian_marketing_platform.server:main
@@ -0,0 +1 @@
1
+ eulerian_marketing_platform