eulerian-marketing-platform 0.2.4__py3-none-any.whl → 0.2.6__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.4"
7
+ __version__ = "0.2.6"
8
8
  __author__ = "Eulerian Technologies"
9
9
  __all__ = []
10
10
 
@@ -74,13 +74,12 @@ def forward_request(request_data: dict) -> dict:
74
74
  request_data: The JSON-RPC request to forward
75
75
 
76
76
  Returns:
77
- The JSON-RPC response from the remote server, or None for notifications
77
+ The JSON-RPC response from the remote server
78
78
  """
79
79
  timeout = float(os.environ.get("EMP_TIMEOUT", "300"))
80
80
 
81
81
  request_id = request_data.get("id")
82
82
  method = request_data.get("method")
83
- is_notification = request_id is None
84
83
 
85
84
  logger.info(f">>> REQUEST: {method} (id: {request_id})")
86
85
  logger.debug(f" Full request: {json.dumps(request_data)[:200]}...")
@@ -101,15 +100,18 @@ def forward_request(request_data: dict) -> dict:
101
100
 
102
101
  logger.info(f"<<< RESPONSE: HTTP {response.status_code}")
103
102
 
103
+ # Handle HTTP 204 No Content (common for notifications)
104
+ if response.status_code == 204:
105
+ logger.info(" HTTP 204 No Content - creating empty success response")
106
+ return {
107
+ "jsonrpc": "2.0",
108
+ "id": request_id,
109
+ "result": {}
110
+ }
111
+
104
112
  if response.status_code != 200:
105
113
  error_msg = f"HTTP {response.status_code}: {response.reason_phrase}"
106
114
  logger.error(f" Error: {response.text[:200]}")
107
-
108
- # For notifications, don't return error responses
109
- if is_notification:
110
- logger.info(" Notification error - no response sent")
111
- return None
112
-
113
115
  return {
114
116
  "jsonrpc": "2.0",
115
117
  "id": request_id,
@@ -119,35 +121,77 @@ def forward_request(request_data: dict) -> dict:
119
121
  }
120
122
  }
121
123
 
122
- # Parse response
124
+ # Parse response for HTTP 200
123
125
  try:
124
126
  response_data = response.json()
125
127
  logger.debug(f" Response: {json.dumps(response_data)[:200]}...")
126
128
 
127
- # For notifications, we should not send back any response, regardless of what the remote server returns
128
- if is_notification:
129
- logger.info(" Notification processed - no response sent")
130
- return None
129
+ # Add detailed logging for different MCP methods
130
+ if "result" in response_data:
131
+ logger.info(" Has 'result' field [OK]")
132
+
133
+ result = response_data.get("result", {})
134
+
135
+ if method == "initialize":
136
+ logger.info(f" Initialize result: protocolVersion={result.get('protocolVersion')}")
137
+ capabilities = result.get("capabilities", {})
138
+ logger.info(f" Server capabilities: {list(capabilities.keys())}")
139
+ server_info = result.get("serverInfo", {})
140
+ logger.info(f" Server info: name={server_info.get('name')}, version={server_info.get('version')}")
141
+
142
+ elif method == "tools/list":
143
+ tools = result.get("tools", [])
144
+ logger.info(f" Tools available: {len(tools)} tools")
145
+ for i, tool in enumerate(tools):
146
+ tool_name = tool.get("name", "unnamed")
147
+ tool_desc = tool.get("description", "no description")[:50]
148
+ logger.info(f" Tool {i+1}: {tool_name} - {tool_desc}")
149
+ # Log input schema info
150
+ input_schema = tool.get("inputSchema", {})
151
+ if "properties" in input_schema:
152
+ props = list(input_schema["properties"].keys())[:3]
153
+ logger.info(f" Input properties: {props}")
154
+
155
+ elif method == "resources/list":
156
+ resources = result.get("resources", [])
157
+ logger.info(f" Resources available: {len(resources)} resources")
158
+ for i, resource in enumerate(resources[:3]):
159
+ res_uri = resource.get("uri", "no uri")
160
+ res_name = resource.get("name", "unnamed")
161
+ logger.info(f" Resource {i+1}: {res_name} ({res_uri})")
162
+ if len(resources) > 3:
163
+ logger.info(f" ... and {len(resources) - 3} more resources")
164
+
165
+ elif method.startswith("tools/call"):
166
+ logger.info(f" Tool call result keys: {list(result.keys())}")
167
+ if "content" in result:
168
+ content = result["content"]
169
+ if isinstance(content, list) and len(content) > 0:
170
+ logger.info(f" Tool returned {len(content)} content items")
171
+ first_item = content[0]
172
+ if isinstance(first_item, dict):
173
+ logger.info(f" First content type: {first_item.get('type', 'unknown')}")
174
+ elif isinstance(content, str):
175
+ logger.info(f" Tool returned string content: {len(content)} chars")
176
+
177
+ else:
178
+ # Generic logging for unknown methods
179
+ logger.info(f" Method '{method}' result keys: {list(result.keys())}")
180
+
181
+ elif "error" in response_data:
182
+ error = response_data["error"]
183
+ error_code = error.get("code", "no code")
184
+ error_message = error.get("message", "no message")
185
+ logger.info(f" Has 'error' field: code={error_code}, message={error_message}")
131
186
 
132
187
  # Validate JSON-RPC response
133
188
  if "jsonrpc" not in response_data:
134
189
  logger.warning(" WARNING: Missing 'jsonrpc' field")
135
190
 
136
- if "result" in response_data:
137
- logger.info(" Has 'result' field [OK]")
138
- elif "error" in response_data:
139
- logger.info(f" Has 'error' field: {response_data['error']}")
140
-
141
191
  return response_data
142
192
 
143
193
  except json.JSONDecodeError as e:
144
194
  logger.error(f" ERROR: Invalid JSON - {e}")
145
-
146
- # For notifications, don't return error responses
147
- if is_notification:
148
- logger.info(" Notification JSON error - no response sent")
149
- return None
150
-
151
195
  return {
152
196
  "jsonrpc": "2.0",
153
197
  "id": request_id,
@@ -159,12 +203,6 @@ def forward_request(request_data: dict) -> dict:
159
203
 
160
204
  except httpx.TimeoutException:
161
205
  logger.error("ERROR: Request timeout")
162
-
163
- # For notifications, don't return error responses
164
- if is_notification:
165
- logger.info(" Notification timeout - no response sent")
166
- return None
167
-
168
206
  return {
169
207
  "jsonrpc": "2.0",
170
208
  "id": request_id,
@@ -176,12 +214,6 @@ def forward_request(request_data: dict) -> dict:
176
214
 
177
215
  except httpx.RequestError as e:
178
216
  logger.error(f"ERROR: Request failed - {str(e)}")
179
-
180
- # For notifications, don't return error responses
181
- if is_notification:
182
- logger.info(" Notification request error - no response sent")
183
- return None
184
-
185
217
  return {
186
218
  "jsonrpc": "2.0",
187
219
  "id": request_id,
@@ -195,12 +227,6 @@ def forward_request(request_data: dict) -> dict:
195
227
  logger.error(f"ERROR: Unexpected error - {str(e)}")
196
228
  import traceback
197
229
  logger.error(f"Traceback: {traceback.format_exc()}")
198
-
199
- # For notifications, don't return error responses
200
- if is_notification:
201
- logger.info(" Notification unexpected error - no response sent")
202
- return None
203
-
204
230
  return {
205
231
  "jsonrpc": "2.0",
206
232
  "id": request_id,
@@ -251,15 +277,12 @@ def main() -> None:
251
277
  # Forward to remote server
252
278
  response_data = forward_request(request_data)
253
279
 
254
- # Only send response for non-notifications (when response_data is not None)
255
- if response_data is not None:
256
- response_json = json.dumps(response_data)
257
- print(response_json, flush=True)
258
- sys.stdout.flush()
259
- logger.info(" Response forwarded [OK]")
260
- else:
261
- logger.info(" Notification processed (no response sent)")
262
-
280
+ # Always send response back to Claude Desktop (MCP requires this)
281
+ response_json = json.dumps(response_data)
282
+ print(response_json, flush=True)
283
+ sys.stdout.flush()
284
+ logger.info(" Response forwarded [OK]")
285
+
263
286
  except json.JSONDecodeError as e:
264
287
  logger.error(f"ERROR: Invalid JSON in request - {e}")
265
288
  logger.error(f" Problematic line: {line[:200]}")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: eulerian-marketing-platform
3
- Version: 0.2.4
3
+ Version: 0.2.6
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
@@ -0,0 +1,8 @@
1
+ eulerian_marketing_platform/__init__.py,sha256=Rchunx1TsnHjirVTZtfMlg6LHXlQupKPi-tYLVZTI00,428
2
+ eulerian_marketing_platform/server.py,sha256=GBuksSr38MWXKNR36mbHaMz8589eElGM6qGt2-zOJdw,13321
3
+ eulerian_marketing_platform-0.2.6.dist-info/LICENSE,sha256=eIqBqE_fRsqQJ8F-2v0e-8WzZqdshsCqnzmqLAWrNHU,1078
4
+ eulerian_marketing_platform-0.2.6.dist-info/METADATA,sha256=VR6nemyIP3yUTR_bbLV1V9K5e48M9WVO3zOssc1jIpM,12169
5
+ eulerian_marketing_platform-0.2.6.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
6
+ eulerian_marketing_platform-0.2.6.dist-info/entry_points.txt,sha256=rrPZptATSS9PUtH9gzCYq0WuP6eahkF-DkdUP1FaYfk,88
7
+ eulerian_marketing_platform-0.2.6.dist-info/top_level.txt,sha256=nidh3T6fw-mLjUqZwQ8AiMScS4usuH0WXW4ZgG4HYCo,28
8
+ eulerian_marketing_platform-0.2.6.dist-info/RECORD,,
@@ -1,8 +0,0 @@
1
- eulerian_marketing_platform/__init__.py,sha256=yW4kcvFCxjR0QpXlCWce62Rff9dLCyAFopXCzhoca7U,428
2
- eulerian_marketing_platform/server.py,sha256=KbzP27uGEBW07R-OGl7qzmYOhcWsz4GbM5l1_NOiQ0Q,11306
3
- eulerian_marketing_platform-0.2.4.dist-info/LICENSE,sha256=eIqBqE_fRsqQJ8F-2v0e-8WzZqdshsCqnzmqLAWrNHU,1078
4
- eulerian_marketing_platform-0.2.4.dist-info/METADATA,sha256=mhmd4RcV0ftcm1le6Reg-UVTwDhNd8e0sizOSq0rV28,12169
5
- eulerian_marketing_platform-0.2.4.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
6
- eulerian_marketing_platform-0.2.4.dist-info/entry_points.txt,sha256=rrPZptATSS9PUtH9gzCYq0WuP6eahkF-DkdUP1FaYfk,88
7
- eulerian_marketing_platform-0.2.4.dist-info/top_level.txt,sha256=nidh3T6fw-mLjUqZwQ8AiMScS4usuH0WXW4ZgG4HYCo,28
8
- eulerian_marketing_platform-0.2.4.dist-info/RECORD,,