eulerian-marketing-platform 0.1.1__py3-none-any.whl → 0.1.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,8 +4,12 @@ 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
- from .server import main
8
-
9
- __version__ = "0.1.1"
7
+ __version__ = "0.1.2"
10
8
  __author__ = "Eulerian Technologies"
11
- __all__ = ["main"]
9
+ __all__ = []
10
+
11
+ # Import main only when explicitly requested
12
+ def get_main():
13
+ """Lazy import of main function to avoid side effects."""
14
+ from .server import main
15
+ return main
@@ -37,15 +37,20 @@ log_dir = os.path.dirname(LOG_FILE)
37
37
  if log_dir: # Only create if there's a directory part
38
38
  os.makedirs(log_dir, exist_ok=True)
39
39
 
40
- # Configure logging to file and stderr
40
+ # Configure logging to file and stderr with UTF-8 encoding for cross-platform compatibility
41
+ file_handler = logging.FileHandler(LOG_FILE, encoding='utf-8')
42
+ file_handler.setLevel(logging.INFO)
43
+ file_handler.setFormatter(logging.Formatter("[%(asctime)s] %(levelname)s: %(message)s", datefmt="%Y-%m-%d %H:%M:%S"))
44
+
45
+ # For stderr, use system encoding with error handling
46
+ stream_handler = logging.StreamHandler(sys.stderr)
47
+ stream_handler.setLevel(logging.INFO)
48
+ stream_handler.setFormatter(logging.Formatter("[%(asctime)s] %(levelname)s: %(message)s", datefmt="%Y-%m-%d %H:%M:%S"))
49
+
50
+ # Configure root logger
41
51
  logging.basicConfig(
42
52
  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
- ]
53
+ handlers=[file_handler, stream_handler]
49
54
  )
50
55
  logger = logging.getLogger(__name__)
51
56
 
@@ -156,137 +161,78 @@ class EulerianMCPProxy:
156
161
  raise Exception(f"Invalid JSON response: {str(e)}")
157
162
 
158
163
 
159
- # Create global proxy instance
160
- proxy = EulerianMCPProxy()
161
-
162
- # Create FastMCP server
163
- mcp = FastMCP("eulerian-marketing-platform")
164
-
165
-
166
164
  # 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": []}
165
+ # (Tools are registered in main() to avoid running on import)
183
166
 
184
167
 
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 = {}
168
+ def main() -> None:
169
+ """Entry point for the MCP proxy server."""
170
+ # Validate configuration before starting
171
+ validate_config()
209
172
 
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.
173
+ # Create proxy and server instances (moved here to avoid running on import)
174
+ global proxy, mcp
175
+ proxy = EulerianMCPProxy()
176
+ mcp = FastMCP("eulerian-marketing-platform")
225
177
 
226
- Resources are data sources that can be read from the Eulerian platform,
227
- such as configuration files, reports, or reference data.
178
+ # Register tools
179
+ @mcp.tool()
180
+ async def list_remote_tools() -> dict[str, Any]:
181
+ """List all available tools from the remote Eulerian MCP server."""
182
+ try:
183
+ result = await proxy.forward_request("tools/list")
184
+ return result
185
+ except Exception as e:
186
+ logger.error(f"Failed to list tools: {str(e)}")
187
+ return {"error": str(e), "tools": []}
228
188
 
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.
189
+ @mcp.tool()
190
+ async def call_eulerian_tool(tool_name: str, arguments: dict[str, Any] = None) -> dict[str, Any]:
191
+ """Call a tool on the remote Eulerian MCP server."""
192
+ if arguments is None:
193
+ arguments = {}
194
+ try:
195
+ params = {"name": tool_name, "arguments": arguments}
196
+ result = await proxy.forward_request("tools/call", params)
197
+ return result
198
+ except Exception as e:
199
+ logger.error(f"Failed to call tool '{tool_name}': {str(e)}")
200
+ return {"error": str(e), "tool": tool_name}
243
201
 
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.
202
+ @mcp.tool()
203
+ async def get_eulerian_resources() -> dict[str, Any]:
204
+ """List all available resources from the remote Eulerian MCP server."""
205
+ try:
206
+ result = await proxy.forward_request("resources/list")
207
+ return result
208
+ except Exception as e:
209
+ logger.error(f"Failed to list resources: {str(e)}")
210
+ return {"error": str(e), "resources": []}
265
211
 
266
- Returns server capabilities, version, and other metadata.
212
+ @mcp.tool()
213
+ async def read_eulerian_resource(uri: str) -> dict[str, Any]:
214
+ """Read a specific resource from the remote Eulerian MCP server."""
215
+ try:
216
+ params = {"uri": uri}
217
+ result = await proxy.forward_request("resources/read", params)
218
+ return result
219
+ except Exception as e:
220
+ logger.error(f"Failed to read resource '{uri}': {str(e)}")
221
+ return {"error": str(e), "uri": uri}
267
222
 
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()
223
+ @mcp.tool()
224
+ async def get_server_info() -> dict[str, Any]:
225
+ """Get information about the remote Eulerian MCP server."""
226
+ try:
227
+ result = await proxy.forward_request("initialize", {
228
+ "protocolVersion": "2024-11-05",
229
+ "capabilities": {},
230
+ "clientInfo": {"name": "eulerian-mcp-proxy", "version": "0.1.1"}
231
+ })
232
+ return result
233
+ except Exception as e:
234
+ logger.error(f"Failed to get server info: {str(e)}")
235
+ return {"error": str(e)}
290
236
 
291
237
  logger.info("Starting Eulerian MCP Proxy Server...")
292
238
  logger.info("Available tools:")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: eulerian-marketing-platform
3
- Version: 0.1.1
3
+ Version: 0.1.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
@@ -0,0 +1,8 @@
1
+ eulerian_marketing_platform/__init__.py,sha256=osuJ8iP6O20ElZXPoZlOQ7sNbZ93kgMz3we8mm_B2-Y,428
2
+ eulerian_marketing_platform/server.py,sha256=bUVn_b05ZritTtNflldCxoFn8YwyrQBqrcbQZ5ceZAg,9810
3
+ eulerian_marketing_platform-0.1.2.dist-info/LICENSE,sha256=eIqBqE_fRsqQJ8F-2v0e-8WzZqdshsCqnzmqLAWrNHU,1078
4
+ eulerian_marketing_platform-0.1.2.dist-info/METADATA,sha256=gfE3v09r1B4dd8Vi_snjgd9JQDWaHplKnZMsp1ML-34,16957
5
+ eulerian_marketing_platform-0.1.2.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
6
+ eulerian_marketing_platform-0.1.2.dist-info/entry_points.txt,sha256=rrPZptATSS9PUtH9gzCYq0WuP6eahkF-DkdUP1FaYfk,88
7
+ eulerian_marketing_platform-0.1.2.dist-info/top_level.txt,sha256=nidh3T6fw-mLjUqZwQ8AiMScS4usuH0WXW4ZgG4HYCo,28
8
+ eulerian_marketing_platform-0.1.2.dist-info/RECORD,,
@@ -1,8 +0,0 @@
1
- eulerian_marketing_platform/__init__.py,sha256=Rn4OZQAUsvh-s5Sq2un79qnJ50dnFvAFr0jMHXMVgWQ,291
2
- eulerian_marketing_platform/server.py,sha256=R7qW5Fclv1sbcFEN5L4Upe6c-BwXsod6Q16Tuyxgc9c,10712
3
- eulerian_marketing_platform-0.1.1.dist-info/LICENSE,sha256=eIqBqE_fRsqQJ8F-2v0e-8WzZqdshsCqnzmqLAWrNHU,1078
4
- eulerian_marketing_platform-0.1.1.dist-info/METADATA,sha256=2U6mXMEf2-RecN3bIB_zspSZCgCcoiIJg67zTCa_pZ4,16957
5
- eulerian_marketing_platform-0.1.1.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
6
- eulerian_marketing_platform-0.1.1.dist-info/entry_points.txt,sha256=rrPZptATSS9PUtH9gzCYq0WuP6eahkF-DkdUP1FaYfk,88
7
- eulerian_marketing_platform-0.1.1.dist-info/top_level.txt,sha256=nidh3T6fw-mLjUqZwQ8AiMScS4usuH0WXW4ZgG4HYCo,28
8
- eulerian_marketing_platform-0.1.1.dist-info/RECORD,,