memra 0.1.2__py3-none-any.whl → 0.2.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.
- memra/__init__.py +17 -21
- memra/discovery.py +15 -0
- memra/execution.py +19 -3
- memra/tool_registry.py +190 -0
- memra/tool_registry_client.py +3 -2
- memra-0.2.0.dist-info/METADATA +161 -0
- memra-0.2.0.dist-info/RECORD +19 -0
- memra-0.2.0.dist-info/entry_points.txt +2 -0
- memra-0.2.0.dist-info/top_level.txt +2 -0
- memra-sdk-package/examples/accounts_payable_client.py +207 -0
- memra-sdk-package/memra/__init__.py +28 -0
- memra-sdk-package/memra/discovery_client.py +49 -0
- memra-sdk-package/memra/execution.py +418 -0
- memra-sdk-package/memra/models.py +98 -0
- memra-sdk-package/memra/tool_registry_client.py +105 -0
- memra-0.1.2.dist-info/METADATA +0 -191
- memra-0.1.2.dist-info/RECORD +0 -10
- memra-0.1.2.dist-info/top_level.txt +0 -1
- {memra-0.1.2.dist-info → memra-0.2.0.dist-info}/WHEEL +0 -0
- {memra-0.1.2.dist-info → memra-0.2.0.dist-info}/licenses/LICENSE +0 -0
memra/__init__.py
CHANGED
@@ -1,28 +1,24 @@
|
|
1
1
|
"""
|
2
|
-
Memra SDK -
|
2
|
+
Memra SDK - Declarative framework for enterprise workflows with MCP integration
|
3
|
+
|
4
|
+
A powerful orchestration framework that allows you to build AI-powered business workflows
|
5
|
+
with hybrid cloud/local execution capabilities.
|
3
6
|
"""
|
4
7
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
DepartmentResult,
|
13
|
-
DepartmentAudit
|
14
|
-
)
|
15
|
-
from .discovery_client import discover_tools, check_api_health, get_api_status
|
8
|
+
__version__ = "0.2.0"
|
9
|
+
__author__ = "Memra"
|
10
|
+
__email__ = "info@memra.co"
|
11
|
+
|
12
|
+
# Core imports
|
13
|
+
from .models import Agent, Department, LLM, Tool
|
14
|
+
from .execution import ExecutionEngine
|
16
15
|
|
17
|
-
|
16
|
+
# Make key classes available at package level
|
18
17
|
__all__ = [
|
19
|
-
"Agent",
|
18
|
+
"Agent",
|
20
19
|
"Department",
|
21
|
-
"LLM",
|
22
|
-
"Tool",
|
23
|
-
"
|
24
|
-
"
|
25
|
-
"DepartmentResult",
|
26
|
-
"DepartmentAudit",
|
27
|
-
"discover_tools"
|
20
|
+
"LLM",
|
21
|
+
"Tool",
|
22
|
+
"ExecutionEngine",
|
23
|
+
"__version__"
|
28
24
|
]
|
memra/discovery.py
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
from typing import List, Dict, Any, Optional
|
2
|
+
from .tool_registry import ToolRegistry
|
3
|
+
|
4
|
+
def discover_tools(hosted_by: Optional[str] = None) -> List[Dict[str, Any]]:
|
5
|
+
"""
|
6
|
+
Discover available tools in the Memra platform.
|
7
|
+
|
8
|
+
Args:
|
9
|
+
hosted_by: Filter tools by host ("memra" or "mcp"). If None, returns all tools.
|
10
|
+
|
11
|
+
Returns:
|
12
|
+
List of available tools with their metadata
|
13
|
+
"""
|
14
|
+
registry = ToolRegistry()
|
15
|
+
return registry.discover_tools(hosted_by)
|
memra/execution.py
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
import time
|
2
2
|
import logging
|
3
|
+
import os
|
3
4
|
from typing import Dict, Any, List, Optional
|
4
5
|
from .models import Department, Agent, DepartmentResult, ExecutionTrace, DepartmentAudit
|
5
|
-
from .tool_registry_client import ToolRegistryClient
|
6
6
|
|
7
7
|
logger = logging.getLogger(__name__)
|
8
8
|
|
@@ -10,7 +10,16 @@ class ExecutionEngine:
|
|
10
10
|
"""Engine that executes department workflows by coordinating agents and tools"""
|
11
11
|
|
12
12
|
def __init__(self):
|
13
|
-
|
13
|
+
# Use API client if MEMRA_API_KEY is set, otherwise use local tools
|
14
|
+
if os.getenv('MEMRA_API_KEY'):
|
15
|
+
from .tool_registry_client import ToolRegistryClient
|
16
|
+
self.tool_registry = ToolRegistryClient()
|
17
|
+
logger.info("Using API client for tool execution")
|
18
|
+
else:
|
19
|
+
from .tool_registry import ToolRegistry
|
20
|
+
self.tool_registry = ToolRegistry()
|
21
|
+
logger.info("Using local tool registry")
|
22
|
+
|
14
23
|
self.last_execution_audit: Optional[DepartmentAudit] = None
|
15
24
|
|
16
25
|
def execute_department(self, department: Department, input_data: Dict[str, Any]) -> DepartmentResult:
|
@@ -194,6 +203,13 @@ class ExecutionEngine:
|
|
194
203
|
tool_name = tool_spec["name"] if isinstance(tool_spec, dict) else tool_spec.name
|
195
204
|
hosted_by = tool_spec.get("hosted_by", "memra") if isinstance(tool_spec, dict) else tool_spec.hosted_by
|
196
205
|
|
206
|
+
# Extract tool-level config if available, otherwise use agent config
|
207
|
+
tool_config = None
|
208
|
+
if isinstance(tool_spec, dict) and "config" in tool_spec:
|
209
|
+
tool_config = tool_spec["config"]
|
210
|
+
elif agent.config:
|
211
|
+
tool_config = agent.config
|
212
|
+
|
197
213
|
print(f"⚡ {agent.role}: Using tool {i}/{len(agent.tools)}: {tool_name}")
|
198
214
|
|
199
215
|
trace.tools_invoked.append(tool_name)
|
@@ -203,7 +219,7 @@ class ExecutionEngine:
|
|
203
219
|
tool_name,
|
204
220
|
hosted_by,
|
205
221
|
agent_input,
|
206
|
-
|
222
|
+
tool_config
|
207
223
|
)
|
208
224
|
|
209
225
|
if not tool_result.get("success", False):
|
memra/tool_registry.py
ADDED
@@ -0,0 +1,190 @@
|
|
1
|
+
import importlib
|
2
|
+
import logging
|
3
|
+
import sys
|
4
|
+
import os
|
5
|
+
from typing import Dict, Any, List, Optional, Callable
|
6
|
+
from pathlib import Path
|
7
|
+
|
8
|
+
logger = logging.getLogger(__name__)
|
9
|
+
|
10
|
+
class ToolRegistry:
|
11
|
+
"""Registry for managing and executing tools"""
|
12
|
+
|
13
|
+
def __init__(self):
|
14
|
+
self.tools: Dict[str, Dict[str, Any]] = {}
|
15
|
+
self._add_project_to_path()
|
16
|
+
self._load_builtin_tools()
|
17
|
+
|
18
|
+
def _add_project_to_path(self):
|
19
|
+
"""Add the project root to Python path so we can import logic modules"""
|
20
|
+
# Get the directory containing this file (memra package)
|
21
|
+
current_dir = Path(__file__).parent
|
22
|
+
# Go up one level to get the project root
|
23
|
+
project_root = current_dir.parent
|
24
|
+
|
25
|
+
if str(project_root) not in sys.path:
|
26
|
+
sys.path.insert(0, str(project_root))
|
27
|
+
|
28
|
+
def _load_builtin_tools(self):
|
29
|
+
"""Load tools from the logic directory"""
|
30
|
+
try:
|
31
|
+
# Load invoice tools
|
32
|
+
from logic.invoice_tools import (
|
33
|
+
DatabaseQueryTool, PDFProcessor, OCRTool,
|
34
|
+
InvoiceExtractionWorkflow, DataValidator, PostgresInsert
|
35
|
+
)
|
36
|
+
|
37
|
+
self.register_tool("DatabaseQueryTool", DatabaseQueryTool, "memra",
|
38
|
+
"Query database schemas and data")
|
39
|
+
self.register_tool("PDFProcessor", PDFProcessor, "memra",
|
40
|
+
"Process PDF files and extract content")
|
41
|
+
self.register_tool("OCRTool", OCRTool, "memra",
|
42
|
+
"Perform OCR on images and documents")
|
43
|
+
self.register_tool("InvoiceExtractionWorkflow", InvoiceExtractionWorkflow, "memra",
|
44
|
+
"Extract structured data from invoices")
|
45
|
+
self.register_tool("DataValidator", DataValidator, "memra",
|
46
|
+
"Validate data against schemas")
|
47
|
+
self.register_tool("PostgresInsert", PostgresInsert, "memra",
|
48
|
+
"Insert data into PostgreSQL database")
|
49
|
+
|
50
|
+
# Load file tools
|
51
|
+
from logic.file_tools import FileReader
|
52
|
+
self.register_tool("FileReader", FileReader, "memra",
|
53
|
+
"Read files from the filesystem")
|
54
|
+
|
55
|
+
logger.info(f"Loaded {len(self.tools)} builtin tools")
|
56
|
+
|
57
|
+
except ImportError as e:
|
58
|
+
logger.warning(f"Could not load some tools: {e}")
|
59
|
+
|
60
|
+
def register_tool(self, name: str, tool_class: type, hosted_by: str, description: str):
|
61
|
+
"""Register a tool in the registry"""
|
62
|
+
self.tools[name] = {
|
63
|
+
"class": tool_class,
|
64
|
+
"hosted_by": hosted_by,
|
65
|
+
"description": description
|
66
|
+
}
|
67
|
+
logger.debug(f"Registered tool: {name} (hosted by {hosted_by})")
|
68
|
+
|
69
|
+
def discover_tools(self, hosted_by: Optional[str] = None) -> List[Dict[str, Any]]:
|
70
|
+
"""Discover available tools, optionally filtered by host"""
|
71
|
+
tools = []
|
72
|
+
for name, info in self.tools.items():
|
73
|
+
if hosted_by is None or info["hosted_by"] == hosted_by:
|
74
|
+
tools.append({
|
75
|
+
"name": name,
|
76
|
+
"hosted_by": info["hosted_by"],
|
77
|
+
"description": info["description"]
|
78
|
+
})
|
79
|
+
return tools
|
80
|
+
|
81
|
+
def execute_tool(self, tool_name: str, hosted_by: str, input_data: Dict[str, Any],
|
82
|
+
config: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
|
83
|
+
"""Execute a tool with the given input data"""
|
84
|
+
if tool_name not in self.tools:
|
85
|
+
return {
|
86
|
+
"success": False,
|
87
|
+
"error": f"Tool '{tool_name}' not found in registry"
|
88
|
+
}
|
89
|
+
|
90
|
+
tool_info = self.tools[tool_name]
|
91
|
+
if tool_info["hosted_by"] != hosted_by:
|
92
|
+
return {
|
93
|
+
"success": False,
|
94
|
+
"error": f"Tool '{tool_name}' is hosted by '{tool_info['hosted_by']}', not '{hosted_by}'"
|
95
|
+
}
|
96
|
+
|
97
|
+
try:
|
98
|
+
# Instantiate tool
|
99
|
+
tool_class = tool_info["class"]
|
100
|
+
|
101
|
+
# Some tools need credentials/config for initialization
|
102
|
+
if tool_name in ["DatabaseQueryTool", "PostgresInsert"]:
|
103
|
+
if "connection" in input_data:
|
104
|
+
# Parse connection string or use credentials
|
105
|
+
credentials = self._parse_connection(input_data["connection"])
|
106
|
+
tool_instance = tool_class(credentials)
|
107
|
+
else:
|
108
|
+
return {
|
109
|
+
"success": False,
|
110
|
+
"error": f"Tool '{tool_name}' requires database credentials"
|
111
|
+
}
|
112
|
+
elif tool_name == "InvoiceExtractionWorkflow":
|
113
|
+
# This tool needs to be instantiated to initialize the LLM client
|
114
|
+
tool_instance = tool_class()
|
115
|
+
else:
|
116
|
+
tool_instance = tool_class()
|
117
|
+
|
118
|
+
# Execute tool based on its type
|
119
|
+
result = self._execute_tool_method(tool_instance, tool_name, input_data, config)
|
120
|
+
|
121
|
+
return {
|
122
|
+
"success": True,
|
123
|
+
"data": result
|
124
|
+
}
|
125
|
+
|
126
|
+
except Exception as e:
|
127
|
+
logger.error(f"Tool execution failed for {tool_name}: {str(e)}")
|
128
|
+
return {
|
129
|
+
"success": False,
|
130
|
+
"error": str(e)
|
131
|
+
}
|
132
|
+
|
133
|
+
def _execute_tool_method(self, tool_instance: Any, tool_name: str,
|
134
|
+
input_data: Dict[str, Any], config: Optional[Dict[str, Any]]) -> Dict[str, Any]:
|
135
|
+
"""Execute the appropriate method on the tool instance"""
|
136
|
+
|
137
|
+
if tool_name == "DatabaseQueryTool":
|
138
|
+
return tool_instance.get_schema("invoices") # Default to invoices table
|
139
|
+
|
140
|
+
elif tool_name == "PDFProcessor":
|
141
|
+
file_path = input_data.get("file", "")
|
142
|
+
return tool_instance.process_pdf(file_path)
|
143
|
+
|
144
|
+
elif tool_name == "OCRTool":
|
145
|
+
# Assume PDF processor output is passed as input
|
146
|
+
return {"extracted_text": tool_instance.extract_text(input_data)}
|
147
|
+
|
148
|
+
elif tool_name == "InvoiceExtractionWorkflow":
|
149
|
+
text = input_data.get("extracted_text", "")
|
150
|
+
schema = input_data.get("invoice_schema", {})
|
151
|
+
return tool_instance.extract_data(text, schema)
|
152
|
+
|
153
|
+
elif tool_name == "DataValidator":
|
154
|
+
data = input_data.get("invoice_data", {})
|
155
|
+
schema = input_data.get("invoice_schema", {})
|
156
|
+
return tool_instance.validate(data, schema)
|
157
|
+
|
158
|
+
elif tool_name == "PostgresInsert":
|
159
|
+
data = input_data.get("invoice_data", {})
|
160
|
+
return tool_instance.insert_record("invoices", data)
|
161
|
+
|
162
|
+
elif tool_name == "FileReader":
|
163
|
+
file_path = config.get("path") if config else input_data.get("file_path")
|
164
|
+
if not file_path:
|
165
|
+
raise ValueError("FileReader requires a file path")
|
166
|
+
return tool_instance.read_file(file_path)
|
167
|
+
|
168
|
+
else:
|
169
|
+
raise ValueError(f"Unknown tool execution method for {tool_name}")
|
170
|
+
|
171
|
+
def _parse_connection(self, connection_string: str) -> Dict[str, Any]:
|
172
|
+
"""Parse a connection string into credentials"""
|
173
|
+
# Simple parser for postgres://user:pass@host:port/database
|
174
|
+
if connection_string.startswith("postgres://"):
|
175
|
+
# This is a simplified parser - in production you'd use a proper URL parser
|
176
|
+
parts = connection_string.replace("postgres://", "").split("/")
|
177
|
+
db_part = parts[1] if len(parts) > 1 else "finance"
|
178
|
+
auth_host = parts[0].split("@")
|
179
|
+
host_port = auth_host[1].split(":") if len(auth_host) > 1 else ["localhost", "5432"]
|
180
|
+
user_pass = auth_host[0].split(":") if len(auth_host) > 1 else ["user", "pass"]
|
181
|
+
|
182
|
+
return {
|
183
|
+
"host": host_port[0],
|
184
|
+
"port": int(host_port[1]) if len(host_port) > 1 else 5432,
|
185
|
+
"database": db_part,
|
186
|
+
"user": user_pass[0],
|
187
|
+
"password": user_pass[1] if len(user_pass) > 1 else ""
|
188
|
+
}
|
189
|
+
|
190
|
+
return {"connection_string": connection_string}
|
memra/tool_registry_client.py
CHANGED
@@ -12,12 +12,13 @@ class ToolRegistryClient:
|
|
12
12
|
def __init__(self):
|
13
13
|
self.api_base = os.getenv("MEMRA_API_URL", "https://api.memra.co")
|
14
14
|
self.api_key = os.getenv("MEMRA_API_KEY")
|
15
|
+
self.tools_cache = None
|
16
|
+
|
15
17
|
if not self.api_key:
|
16
18
|
raise ValueError(
|
17
19
|
"MEMRA_API_KEY environment variable is required. "
|
18
|
-
"
|
20
|
+
"Please contact info@memra.co for an API key."
|
19
21
|
)
|
20
|
-
self.tools_cache = None
|
21
22
|
|
22
23
|
def discover_tools(self, hosted_by: Optional[str] = None) -> List[Dict[str, Any]]:
|
23
24
|
"""Discover available tools from the API"""
|
@@ -0,0 +1,161 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: memra
|
3
|
+
Version: 0.2.0
|
4
|
+
Summary: Declarative framework for enterprise workflows with MCP integration
|
5
|
+
Home-page: https://github.com/memra/memra-sdk
|
6
|
+
Author: Memra
|
7
|
+
Author-email: Memra <info@memra.co>
|
8
|
+
License: MIT
|
9
|
+
Project-URL: Homepage, https://memra.co
|
10
|
+
Project-URL: Repository, https://github.com/memra-platform/memra-sdk
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
12
|
+
Classifier: Intended Audience :: Developers
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
14
|
+
Classifier: Operating System :: OS Independent
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
16
|
+
Classifier: Programming Language :: Python :: 3.8
|
17
|
+
Classifier: Programming Language :: Python :: 3.9
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
20
|
+
Requires-Python: >=3.8
|
21
|
+
Description-Content-Type: text/markdown
|
22
|
+
License-File: LICENSE
|
23
|
+
Requires-Dist: pydantic>=1.8.0
|
24
|
+
Requires-Dist: httpx>=0.24.0
|
25
|
+
Requires-Dist: typing-extensions>=4.0.0
|
26
|
+
Requires-Dist: aiohttp>=3.8.0
|
27
|
+
Requires-Dist: aiohttp-cors>=0.7.0
|
28
|
+
Requires-Dist: psycopg2-binary>=2.9.0
|
29
|
+
Provides-Extra: dev
|
30
|
+
Requires-Dist: pytest>=6.0; extra == "dev"
|
31
|
+
Requires-Dist: pytest-asyncio; extra == "dev"
|
32
|
+
Requires-Dist: black; extra == "dev"
|
33
|
+
Requires-Dist: flake8; extra == "dev"
|
34
|
+
Dynamic: author
|
35
|
+
Dynamic: home-page
|
36
|
+
Dynamic: license-file
|
37
|
+
Dynamic: requires-python
|
38
|
+
|
39
|
+
# Memra SDK
|
40
|
+
|
41
|
+
A declarative orchestration framework for AI-powered business workflows. Think of it as "Kubernetes for business logic" where agents are the pods and departments are the deployments.
|
42
|
+
|
43
|
+
## 🚀 Team Setup
|
44
|
+
|
45
|
+
**New team member?** See the complete setup guide: **[TEAM_SETUP.md](TEAM_SETUP.md)**
|
46
|
+
|
47
|
+
This includes:
|
48
|
+
- Database setup (PostgreSQL + Docker)
|
49
|
+
- Local development environment
|
50
|
+
- Testing instructions
|
51
|
+
- Troubleshooting guide
|
52
|
+
|
53
|
+
## Quick Start
|
54
|
+
|
55
|
+
```python
|
56
|
+
from memra.sdk.models import Agent, Department, Tool
|
57
|
+
|
58
|
+
# Define your agents
|
59
|
+
data_extractor = Agent(
|
60
|
+
role="Data Extraction Specialist",
|
61
|
+
job="Extract and validate data",
|
62
|
+
tools=[Tool(name="DataExtractor", hosted_by="memra")],
|
63
|
+
input_keys=["input_data"],
|
64
|
+
output_key="extracted_data"
|
65
|
+
)
|
66
|
+
|
67
|
+
# Create a department
|
68
|
+
dept = Department(
|
69
|
+
name="Data Processing",
|
70
|
+
mission="Process and validate data",
|
71
|
+
agents=[data_extractor]
|
72
|
+
)
|
73
|
+
|
74
|
+
# Run the workflow
|
75
|
+
result = dept.run({"input_data": {...}})
|
76
|
+
```
|
77
|
+
|
78
|
+
## Installation
|
79
|
+
|
80
|
+
```bash
|
81
|
+
pip install memra
|
82
|
+
```
|
83
|
+
|
84
|
+
## API Access
|
85
|
+
|
86
|
+
Memra requires an API key to execute workflows on the hosted infrastructure.
|
87
|
+
|
88
|
+
### Get Your API Key
|
89
|
+
Contact [info@memra.co](mailto:info@memra.co) for API access.
|
90
|
+
|
91
|
+
### Set Your API Key
|
92
|
+
```bash
|
93
|
+
# Set environment variable
|
94
|
+
export MEMRA_API_KEY="your-api-key-here"
|
95
|
+
|
96
|
+
# Or add to your shell profile for persistence
|
97
|
+
echo 'export MEMRA_API_KEY="your-api-key-here"' >> ~/.zshrc
|
98
|
+
```
|
99
|
+
|
100
|
+
### Test Your Setup
|
101
|
+
```bash
|
102
|
+
python examples/accounts_payable_client.py
|
103
|
+
```
|
104
|
+
|
105
|
+
## Documentation
|
106
|
+
|
107
|
+
Documentation is coming soon. For now, see the examples below and in the `examples/` directory.
|
108
|
+
|
109
|
+
## Example: Propane Delivery Workflow
|
110
|
+
|
111
|
+
See the `examples/propane_delivery.py` file for a complete example of how to use Memra to orchestrate a propane delivery workflow.
|
112
|
+
|
113
|
+
## Contributing
|
114
|
+
|
115
|
+
We welcome contributions! Please see our [contributing guide](CONTRIBUTING.md) for details.
|
116
|
+
|
117
|
+
## License
|
118
|
+
|
119
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
120
|
+
|
121
|
+
## Examples
|
122
|
+
|
123
|
+
```
|
124
|
+
├── examples/
|
125
|
+
│ ├── accounts_payable_client.py # API-based example
|
126
|
+
│ ├── accounts_payable.py # Local example
|
127
|
+
│ ├── invoice_processing.py # Simple workflow
|
128
|
+
│ └── propane_delivery.py # Domain example
|
129
|
+
├── memra/ # Core SDK
|
130
|
+
├── logic/ # Tool implementations
|
131
|
+
├── local/dependencies/ # Database setup & schemas
|
132
|
+
└── docker-compose.yml # Database setup
|
133
|
+
```
|
134
|
+
|
135
|
+
## ✨ New: MCP Integration
|
136
|
+
|
137
|
+
Memra now supports **Model Context Protocol (MCP)** integration, allowing you to execute operations on your local infrastructure while leveraging Memra's cloud-based AI processing.
|
138
|
+
|
139
|
+
**Key Benefits:**
|
140
|
+
- 🔒 **Keep sensitive data local** - Your databases stay on your infrastructure
|
141
|
+
- ⚡ **Hybrid processing** - AI processing in the cloud, data operations locally
|
142
|
+
- 🔐 **Secure communication** - HMAC-authenticated requests between cloud and local
|
143
|
+
- 🛠️ **Easy setup** - Simple bridge server connects your local resources
|
144
|
+
|
145
|
+
**Quick Example:**
|
146
|
+
```python
|
147
|
+
# Agent that uses local database via MCP
|
148
|
+
agent = Agent(
|
149
|
+
role="Data Writer",
|
150
|
+
tools=[{
|
151
|
+
"name": "PostgresInsert",
|
152
|
+
"hosted_by": "mcp", # Routes to your local infrastructure
|
153
|
+
"config": {
|
154
|
+
"bridge_url": "http://localhost:8081",
|
155
|
+
"bridge_secret": "your-secret"
|
156
|
+
}
|
157
|
+
}]
|
158
|
+
)
|
159
|
+
```
|
160
|
+
|
161
|
+
📖 **[Complete MCP Integration Guide →](docs/mcp_integration.md)**
|
@@ -0,0 +1,19 @@
|
|
1
|
+
memra/__init__.py,sha256=XLSWpo42Ffp_pi5mvk4xvdYBZ8eNLAJF4_3Oi102i90,560
|
2
|
+
memra/discovery.py,sha256=yJIQnrDQu1nyzKykCIuzG_5SW5dIXHCEBLLKRWacIoY,480
|
3
|
+
memra/discovery_client.py,sha256=AbnKn6qhyrf7vmOvknEeDzH4tiGHsqPHtDaein_qaW0,1271
|
4
|
+
memra/execution.py,sha256=5NIyFVtQEeatYQ-fxexT0eWMtCh28k1hRC2Y6cfQaac,20917
|
5
|
+
memra/models.py,sha256=nTaYLAp0tRzQ0CQaBLNBURfhBQ5_gyty0ams4mghyIc,3289
|
6
|
+
memra/tool_registry.py,sha256=zdyKRShcmKtG7BVfmAHflW9FDl7rooPPAgbdVV4gJ8o,8268
|
7
|
+
memra/tool_registry_client.py,sha256=uzMQ4COvRams9vuPLcqcdljUpDlAYU_tyFxrRhrA0Lc,4009
|
8
|
+
memra-0.2.0.dist-info/licenses/LICENSE,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
9
|
+
memra-sdk-package/examples/accounts_payable_client.py,sha256=Vu_h5C-qc6_80uz5dXJH4G3zfIbgUNAhQ2y8mWauao0,7401
|
10
|
+
memra-sdk-package/memra/__init__.py,sha256=QRk72YETLgL15GVt26tN_rBraCQkhZO7UB9T6d4u_uU,543
|
11
|
+
memra-sdk-package/memra/discovery_client.py,sha256=AbnKn6qhyrf7vmOvknEeDzH4tiGHsqPHtDaein_qaW0,1271
|
12
|
+
memra-sdk-package/memra/execution.py,sha256=UJ_MJ4getuSk4HJW1sCi7lc26avX-G6-GxnvE-DiSwk,20191
|
13
|
+
memra-sdk-package/memra/models.py,sha256=nTaYLAp0tRzQ0CQaBLNBURfhBQ5_gyty0ams4mghyIc,3289
|
14
|
+
memra-sdk-package/memra/tool_registry_client.py,sha256=KyNNxj84248E-8MoWNj6pJmlllUG8s0lmeXXmbu0U7o,3996
|
15
|
+
memra-0.2.0.dist-info/METADATA,sha256=eOuvH39VFUh-QxTdE5RwT6isgRIJkptEC2lsqlF2AA4,4816
|
16
|
+
memra-0.2.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
17
|
+
memra-0.2.0.dist-info/entry_points.txt,sha256=LBVjwWoxWJRzNLgeByPn6xUvWFIRnqnemvAZgIoSt08,41
|
18
|
+
memra-0.2.0.dist-info/top_level.txt,sha256=5dqePB77aj_pPFavlwxtBvdkUM-kP-WiQD3LRbQswwc,24
|
19
|
+
memra-0.2.0.dist-info/RECORD,,
|