yomemoai-mcp 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.
- yomemoai_mcp/__init__.py +2 -0
- yomemoai_mcp/client.py +131 -0
- yomemoai_mcp/py.typed +0 -0
- yomemoai_mcp/server.py +80 -0
- yomemoai_mcp-0.1.0.dist-info/METADATA +234 -0
- yomemoai_mcp-0.1.0.dist-info/RECORD +9 -0
- yomemoai_mcp-0.1.0.dist-info/WHEEL +4 -0
- yomemoai_mcp-0.1.0.dist-info/entry_points.txt +4 -0
- yomemoai_mcp-0.1.0.dist-info/licenses/LICENSE +21 -0
yomemoai_mcp/__init__.py
ADDED
yomemoai_mcp/client.py
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import base64
|
|
2
|
+
import json
|
|
3
|
+
import time
|
|
4
|
+
import requests
|
|
5
|
+
from typing import Dict, List, Optional, Tuple
|
|
6
|
+
from cryptography.hazmat.primitives import hashes, serialization
|
|
7
|
+
from cryptography.hazmat.primitives.asymmetric import padding
|
|
8
|
+
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
|
|
9
|
+
from cryptography.hazmat.backends import default_backend
|
|
10
|
+
import os
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class MemoClient:
|
|
14
|
+
"""
|
|
15
|
+
Client for yomemoai API
|
|
16
|
+
It's a wrapper for the yomemoai API.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
def __init__(self, api_key: str, private_key_pem: str, base_url: str):
|
|
20
|
+
self.api_key = api_key
|
|
21
|
+
self.base_url = base_url.rstrip('/')
|
|
22
|
+
self.private_key = serialization.load_pem_private_key(
|
|
23
|
+
self._normalize_pem(private_key_pem),
|
|
24
|
+
password=None,
|
|
25
|
+
backend=default_backend()
|
|
26
|
+
)
|
|
27
|
+
self.public_key = self.private_key.public_key()
|
|
28
|
+
self.session = requests.Session()
|
|
29
|
+
self.session.headers.update(
|
|
30
|
+
{"X-Memo-API-Key": self.api_key, "Content-Type": "application/json"})
|
|
31
|
+
|
|
32
|
+
def _normalize_pem(self, pem_str: str) -> bytes:
|
|
33
|
+
pem_str = pem_str.strip()
|
|
34
|
+
if "-----BEGIN" not in pem_str:
|
|
35
|
+
return f"-----BEGIN PRIVATE KEY-----\n{pem_str}\n-----END PRIVATE KEY-----".encode()
|
|
36
|
+
return pem_str.encode()
|
|
37
|
+
|
|
38
|
+
def pack_data(self, raw_data: bytes) -> str:
|
|
39
|
+
aes_key = os.urandom(32)
|
|
40
|
+
nonce = os.urandom(12)
|
|
41
|
+
|
|
42
|
+
cipher = Cipher(algorithms.AES(aes_key), modes.GCM(
|
|
43
|
+
nonce), backend=default_backend())
|
|
44
|
+
encryptor = cipher.encryptor()
|
|
45
|
+
ciphertext = encryptor.update(raw_data) + encryptor.finalize()
|
|
46
|
+
|
|
47
|
+
combined_data = base64.b64encode(
|
|
48
|
+
nonce + ciphertext + encryptor.tag).decode('utf-8')
|
|
49
|
+
|
|
50
|
+
encrypted_key = self.public_key.encrypt(
|
|
51
|
+
aes_key,
|
|
52
|
+
padding.OAEP(mgf=padding.MGF1(algorithm=hashes.SHA256()),
|
|
53
|
+
algorithm=hashes.SHA256(), label=None)
|
|
54
|
+
)
|
|
55
|
+
key_base64 = base64.b64encode(encrypted_key).decode('utf-8')
|
|
56
|
+
|
|
57
|
+
signature = self.private_key.sign(
|
|
58
|
+
combined_data.encode('utf-8'),
|
|
59
|
+
padding.PKCS1v15(),
|
|
60
|
+
hashes.SHA256()
|
|
61
|
+
)
|
|
62
|
+
sig_base64 = base64.b64encode(signature).decode('utf-8')
|
|
63
|
+
|
|
64
|
+
pkg = {
|
|
65
|
+
"data": combined_data,
|
|
66
|
+
"key": key_base64,
|
|
67
|
+
"signature": sig_base64
|
|
68
|
+
}
|
|
69
|
+
return base64.b64encode(json.dumps(pkg).encode()).decode()
|
|
70
|
+
|
|
71
|
+
def unpack_and_decrypt(self, encrypted_pkg_base64: str) -> bytes:
|
|
72
|
+
pkg_json = base64.b64decode(encrypted_pkg_base64)
|
|
73
|
+
pkg = json.loads(pkg_json)
|
|
74
|
+
|
|
75
|
+
if "key" in pkg and pkg["key"]:
|
|
76
|
+
encrypted_key = base64.b64decode(pkg["key"])
|
|
77
|
+
aes_key = self.private_key.decrypt(
|
|
78
|
+
encrypted_key,
|
|
79
|
+
padding.OAEP(mgf=padding.MGF1(algorithm=hashes.SHA256()),
|
|
80
|
+
algorithm=hashes.SHA256(), label=None)
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
combined_data = base64.b64decode(pkg["data"])
|
|
84
|
+
nonce = combined_data[:12]
|
|
85
|
+
tag = combined_data[-16:]
|
|
86
|
+
ciphertext = combined_data[12:-16]
|
|
87
|
+
|
|
88
|
+
cipher = Cipher(algorithms.AES(aes_key), modes.GCM(
|
|
89
|
+
nonce, tag), backend=default_backend())
|
|
90
|
+
decryptor = cipher.decryptor()
|
|
91
|
+
return decryptor.update(ciphertext) + decryptor.finalize()
|
|
92
|
+
else:
|
|
93
|
+
data = base64.b64decode(pkg["data"])
|
|
94
|
+
return self.private_key.decrypt(
|
|
95
|
+
data,
|
|
96
|
+
padding.OAEP(mgf=padding.MGF1(algorithm=hashes.SHA256()),
|
|
97
|
+
algorithm=hashes.SHA256(), label=None)
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
def add_memory(self, content: str, handle: str = "", description: str = "", metadata: Dict = None):
|
|
101
|
+
token_size = len(content)
|
|
102
|
+
|
|
103
|
+
packed = self.pack_data(content.encode('utf-8'))
|
|
104
|
+
payload = {
|
|
105
|
+
"ciphertext": packed,
|
|
106
|
+
"description": description,
|
|
107
|
+
"handle": handle,
|
|
108
|
+
"metadata": metadata or {
|
|
109
|
+
"token_size": token_size,
|
|
110
|
+
"from": "yomemoai-mcp",
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
resp = self.session.post(
|
|
114
|
+
f"{self.base_url}/api/v1/memory", json=payload)
|
|
115
|
+
resp.raise_for_status()
|
|
116
|
+
return resp.json()
|
|
117
|
+
|
|
118
|
+
def get_memories(self, handle: Optional[str] = None) -> List[Dict]:
|
|
119
|
+
url = f"{self.base_url}/api/v1/memory"
|
|
120
|
+
params = {"handle": handle} if handle else {}
|
|
121
|
+
resp = self.session.get(url, params=params)
|
|
122
|
+
resp.raise_for_status()
|
|
123
|
+
|
|
124
|
+
memories = resp.json().get("data", [])
|
|
125
|
+
for m in memories:
|
|
126
|
+
try:
|
|
127
|
+
decrypted = self.unpack_and_decrypt(m["content"])
|
|
128
|
+
m["content"] = decrypted.decode('utf-8')
|
|
129
|
+
except Exception as e:
|
|
130
|
+
print(f"Decryption failed for {m.get('id')}: {e}")
|
|
131
|
+
return memories
|
yomemoai_mcp/py.typed
ADDED
|
File without changes
|
yomemoai_mcp/server.py
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
from mcp.server.fastmcp import FastMCP
|
|
3
|
+
from .client import MemoClient
|
|
4
|
+
import os
|
|
5
|
+
|
|
6
|
+
from dotenv import load_dotenv
|
|
7
|
+
load_dotenv()
|
|
8
|
+
|
|
9
|
+
mcp = FastMCP("yomemoai")
|
|
10
|
+
|
|
11
|
+
API_KEY = os.getenv("MEMO_API_KEY", "")
|
|
12
|
+
PRIV_KEY_PATH = os.getenv("MEMO_PRIVATE_KEY_PATH", "private.pem")
|
|
13
|
+
BASE_URL = os.getenv("MEMO_BASE_URL", "https://api.yomemo.ai")
|
|
14
|
+
|
|
15
|
+
if not API_KEY:
|
|
16
|
+
raise ValueError("MEMO_API_KEY environment variable is required")
|
|
17
|
+
|
|
18
|
+
if not os.path.exists(PRIV_KEY_PATH):
|
|
19
|
+
raise FileNotFoundError(
|
|
20
|
+
f"Private key file not found: {PRIV_KEY_PATH}. "
|
|
21
|
+
f"Please set MEMO_PRIVATE_KEY_PATH environment variable or place your private key at {PRIV_KEY_PATH}"
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
try:
|
|
25
|
+
with open(PRIV_KEY_PATH, "r") as f:
|
|
26
|
+
private_pem = f.read()
|
|
27
|
+
except Exception as e:
|
|
28
|
+
raise IOError(f"Failed to read private key from {PRIV_KEY_PATH}: {e}")
|
|
29
|
+
|
|
30
|
+
if not private_pem.strip():
|
|
31
|
+
raise ValueError(f"Private key file {PRIV_KEY_PATH} is empty")
|
|
32
|
+
|
|
33
|
+
client = MemoClient(API_KEY, private_pem, BASE_URL)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@mcp.tool()
|
|
37
|
+
async def save_memory(content: str, handle: str = "general", description: str = "") -> str:
|
|
38
|
+
"""
|
|
39
|
+
Store important information, user preferences, or conversation context as a permanent memory.
|
|
40
|
+
Use this tool when the user explicitly asks to 'remember', 'save', or 'keep track of' something.
|
|
41
|
+
|
|
42
|
+
:param content: The actual text/information to be remembered. Be concise but maintain context.
|
|
43
|
+
:param handle: A short, unique category or tag (e.g., 'work', 'personal', 'project-x'). Defaults to 'general'.
|
|
44
|
+
:param description: A brief summary of what this memory is about to help with future identification. don't include any sensitive information.
|
|
45
|
+
"""
|
|
46
|
+
try:
|
|
47
|
+
result = client.add_memory(
|
|
48
|
+
content, handle=handle, description=description)
|
|
49
|
+
return f"Successfully archived in memory. ID: {result.get('memory_id')}"
|
|
50
|
+
except Exception as e:
|
|
51
|
+
return f"Failed to save memory: {str(e)}"
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
@mcp.tool()
|
|
55
|
+
async def load_memories(handle: str = None) -> str:
|
|
56
|
+
"""
|
|
57
|
+
Retrieve previously stored memories or context.
|
|
58
|
+
Use this tool when the user asks 'what do you remember about...', 'check my notes on...', or when
|
|
59
|
+
you need historical context to answer a question accurately.
|
|
60
|
+
|
|
61
|
+
:param handle: Optional filter. If the user specifies a category (e.g., 'about my job'),
|
|
62
|
+
extract and provide the relevant handle.
|
|
63
|
+
"""
|
|
64
|
+
try:
|
|
65
|
+
memories = client.get_memories(handle=handle)
|
|
66
|
+
if not memories:
|
|
67
|
+
return f"No memories found under the handle: {handle if handle else 'all'}."
|
|
68
|
+
|
|
69
|
+
output = ["### Retrieved Memories:"]
|
|
70
|
+
for m in memories:
|
|
71
|
+
timestamp = m.get('created_at', 'N/A')
|
|
72
|
+
output.append(
|
|
73
|
+
f"Handle: [{m.get('handle')}]\nContent: {m.get('content')}\n---"
|
|
74
|
+
)
|
|
75
|
+
return "\n".join(output)
|
|
76
|
+
except Exception as e:
|
|
77
|
+
return f"Error retrieving memories: {str(e)}"
|
|
78
|
+
|
|
79
|
+
if __name__ == "__main__":
|
|
80
|
+
mcp.run()
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: yomemoai-mcp
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Model Context Protocol (MCP) server for YoMemoAI - enables AI assistants to save and retrieve encrypted memories
|
|
5
|
+
Author-email: lvxiangxiang <lvxiangxiang@shopline.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Keywords: ai,claude,cursor,mcp,mcp-server,memory,yomemoai
|
|
9
|
+
Classifier: Development Status :: 4 - Beta
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
15
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
16
|
+
Requires-Python: >=3.12
|
|
17
|
+
Requires-Dist: cryptography>=46.0.3
|
|
18
|
+
Requires-Dist: fastmcp>=0.1.0
|
|
19
|
+
Requires-Dist: mcp>=1.25.0
|
|
20
|
+
Requires-Dist: python-dotenv>=1.2.1
|
|
21
|
+
Requires-Dist: requests>=2.32.5
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
|
|
24
|
+
# yomemoai-mcp
|
|
25
|
+
|
|
26
|
+
A Model Context Protocol (MCP) server for YoMemoAI, enabling AI assistants to save and retrieve encrypted memories.
|
|
27
|
+
|
|
28
|
+
## Features
|
|
29
|
+
|
|
30
|
+
- 🔐 **Secure Storage**: Encrypted memory storage using RSA-OAEP and AES-GCM
|
|
31
|
+
- 🏷️ **Categorization**: Organize memories with handles (tags/categories)
|
|
32
|
+
- 🔍 **Retrieval**: Query memories by handle or retrieve all memories
|
|
33
|
+
- 🚀 **MCP Integration**: Seamlessly integrates with MCP-compatible AI assistants
|
|
34
|
+
|
|
35
|
+
## Prerequisites
|
|
36
|
+
|
|
37
|
+
- Python 3.12 or higher
|
|
38
|
+
- [uv](https://github.com/astral-sh/uv) package manager
|
|
39
|
+
- YoMemoAI API key
|
|
40
|
+
- RSA private key (PEM format)
|
|
41
|
+
|
|
42
|
+
## Installation
|
|
43
|
+
|
|
44
|
+
1. Clone the repository:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
git clone <repository-url>
|
|
48
|
+
cd yomemoai-mcp
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
2. Install dependencies using uv:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
uv sync
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Configuration
|
|
58
|
+
|
|
59
|
+
Create a `.env` file in the project root with the following configuration:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
# YoMemoAI MCP Server Configuration
|
|
63
|
+
|
|
64
|
+
# Your API key from YoMemoAI (required)
|
|
65
|
+
MEMO_API_KEY=your_api_key_here
|
|
66
|
+
|
|
67
|
+
# Path to your private key file (RSA private key in PEM format)
|
|
68
|
+
# Default: private.pem
|
|
69
|
+
MEMO_PRIVATE_KEY_PATH=private.pem
|
|
70
|
+
|
|
71
|
+
# Base URL of the YoMemoAI API (optional)
|
|
72
|
+
# Default: https://api.yomemo.ai
|
|
73
|
+
MEMO_BASE_URL=https://api.yomemo.ai
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
**Important Configuration Notes:**
|
|
77
|
+
|
|
78
|
+
1. **MEMO_API_KEY** (required): Your YoMemoAI API key. You must obtain this from your YoMemoAI account.
|
|
79
|
+
|
|
80
|
+
2. **MEMO_PRIVATE_KEY_PATH**: Path to your RSA private key file. The private key should be in PEM format:
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
-----BEGIN PRIVATE KEY-----
|
|
84
|
+
...
|
|
85
|
+
-----END PRIVATE KEY-----
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Make sure this file is secure and never commit it to version control.
|
|
89
|
+
|
|
90
|
+
3. **MEMO_BASE_URL** (optional): The API base URL. Defaults to `https://api.yomemo.ai` if not specified.
|
|
91
|
+
|
|
92
|
+
## Usage
|
|
93
|
+
|
|
94
|
+
### Running the MCP Server
|
|
95
|
+
|
|
96
|
+
After configuration, you can run the MCP server using:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
uv run memo-mcp
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Integration with Cursor/Claude Desktop
|
|
103
|
+
|
|
104
|
+
Add the following configuration to your MCP settings file:
|
|
105
|
+
|
|
106
|
+
**For Cursor**: `~/.cursor/mcp.json` (or `%APPDATA%\Cursor\User\mcp.json` on Windows)
|
|
107
|
+
**For Claude Desktop**: `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows)
|
|
108
|
+
|
|
109
|
+
#### Option 1: Using `uvx` (Recommended - after publishing to PyPI)
|
|
110
|
+
|
|
111
|
+
If the package is published to PyPI, you can use `uvx` to run it directly. The package provides multiple entry points:
|
|
112
|
+
|
|
113
|
+
**Using `uvx yomemoai-mcp`** (recommended):
|
|
114
|
+
|
|
115
|
+
```json
|
|
116
|
+
{
|
|
117
|
+
"mcpServers": {
|
|
118
|
+
"yomemoai": {
|
|
119
|
+
"command": "uvx",
|
|
120
|
+
"args": ["yomemoai-mcp"],
|
|
121
|
+
"env": {
|
|
122
|
+
"MEMO_API_KEY": "your_api_key_here",
|
|
123
|
+
"MEMO_PRIVATE_KEY_PATH": "/absolute/path/to/private.pem",
|
|
124
|
+
"MEMO_BASE_URL": "https://api.yomemo.ai"
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
**How `uvx` works:**
|
|
132
|
+
|
|
133
|
+
- `uvx` automatically downloads the package from PyPI (if not already installed)
|
|
134
|
+
- It runs the package's entry point script defined in `project.scripts`
|
|
135
|
+
- The package name is `yomemoai-mcp`, so `uvx yomemoai-mcp` will automatically use the `yomemoai-mcp` entry point
|
|
136
|
+
- The package also provides alternative entry points: `yomemo` and `memo-mcp` (all point to the same server)
|
|
137
|
+
|
|
138
|
+
**Note**: The package must be published to PyPI before using `uvx`. If the package is not yet published, use Option 2 for local development.
|
|
139
|
+
|
|
140
|
+
#### Option 2: Using local development setup
|
|
141
|
+
|
|
142
|
+
For local development or if the package is not yet published, use the `uv --directory` approach:
|
|
143
|
+
|
|
144
|
+
```json
|
|
145
|
+
{
|
|
146
|
+
"mcpServers": {
|
|
147
|
+
"yomemoai": {
|
|
148
|
+
"command": "uv",
|
|
149
|
+
"args": [
|
|
150
|
+
"--directory",
|
|
151
|
+
"/absolute/path/to/yomemoai-mcp",
|
|
152
|
+
"run",
|
|
153
|
+
"yomemoai-mcp"
|
|
154
|
+
],
|
|
155
|
+
"env": {
|
|
156
|
+
"MEMO_API_KEY": "your_api_key_here",
|
|
157
|
+
"MEMO_PRIVATE_KEY_PATH": "/absolute/path/to/private.pem",
|
|
158
|
+
"MEMO_BASE_URL": "https://api.yomemo.ai"
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
**Important Notes:**
|
|
166
|
+
|
|
167
|
+
- **For Option 1 (`uvx`)**: The package must be published to PyPI. `uvx` will automatically handle installation and execution.
|
|
168
|
+
- **For Option 2 (local)**: Replace `/absolute/path/to/yomemoai-mcp` with the **absolute path** to this repository on your system
|
|
169
|
+
- Replace `/absolute/path/to/private.pem` with the **absolute path** to your private key file
|
|
170
|
+
- The `env` section in the MCP config will override any `.env` file in the project directory
|
|
171
|
+
- After updating the MCP config, restart Cursor/Claude Desktop for changes to take effect
|
|
172
|
+
|
|
173
|
+
### Available Tools
|
|
174
|
+
|
|
175
|
+
#### `save_memory`
|
|
176
|
+
|
|
177
|
+
Store important information, user preferences, or conversation context as a permanent memory.
|
|
178
|
+
|
|
179
|
+
**Parameters:**
|
|
180
|
+
|
|
181
|
+
- `content` (required): The actual text/information to be remembered
|
|
182
|
+
- `handle` (optional): A short, unique category or tag (e.g., 'work', 'personal', 'project-x'). Defaults to 'general'
|
|
183
|
+
- `description` (optional): A brief summary of what this memory is about
|
|
184
|
+
|
|
185
|
+
#### `load_memories`
|
|
186
|
+
|
|
187
|
+
Retrieve previously stored memories or context.
|
|
188
|
+
|
|
189
|
+
**Parameters:**
|
|
190
|
+
|
|
191
|
+
- `handle` (optional): Filter memories by category. If not specified, returns all memories
|
|
192
|
+
|
|
193
|
+
## Development
|
|
194
|
+
|
|
195
|
+
### Project Structure
|
|
196
|
+
|
|
197
|
+
```
|
|
198
|
+
yomemoai-mcp/
|
|
199
|
+
├── src/
|
|
200
|
+
│ └── yomemoai_mcp/
|
|
201
|
+
│ ├── __init__.py
|
|
202
|
+
│ ├── server.py # MCP server implementation
|
|
203
|
+
│ ├── client.py # YoMemoAI API client
|
|
204
|
+
│ └── py.typed # Type hints marker
|
|
205
|
+
├── pyproject.toml # Project configuration
|
|
206
|
+
├── uv.lock # Dependency lock file
|
|
207
|
+
└── README.md
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### Dependencies
|
|
211
|
+
|
|
212
|
+
- `cryptography`: For encryption/decryption operations
|
|
213
|
+
- `fastmcp`: FastMCP framework for MCP servers
|
|
214
|
+
- `mcp`: Model Context Protocol SDK
|
|
215
|
+
- `python-dotenv`: Environment variable management
|
|
216
|
+
- `requests`: HTTP client for API calls
|
|
217
|
+
|
|
218
|
+
## Security Notes
|
|
219
|
+
|
|
220
|
+
- **Never commit** your `.env` file or private key files to version control
|
|
221
|
+
- Keep your private key secure and never share it
|
|
222
|
+
- The `.env` file is already included in `.gitignore`
|
|
223
|
+
|
|
224
|
+
## License
|
|
225
|
+
|
|
226
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
227
|
+
|
|
228
|
+
## Contributing
|
|
229
|
+
|
|
230
|
+
[Add contribution guidelines here]
|
|
231
|
+
|
|
232
|
+
## Support
|
|
233
|
+
|
|
234
|
+
For issues and questions, please open an issue on the repository.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
yomemoai_mcp/__init__.py,sha256=I2FoPD8dKHgF95vpefoGxZkQ9gi9yeYkEM2ZObyUQ48,58
|
|
2
|
+
yomemoai_mcp/client.py,sha256=vNPnYJAYpdZlnYXBKyyx618-sAtNSzZNTRXENw4G8uo,4850
|
|
3
|
+
yomemoai_mcp/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
+
yomemoai_mcp/server.py,sha256=3J-RLInsVz2ALTQV1YyAQti9mG7Y5YPfYXXO_sYprzg,2973
|
|
5
|
+
yomemoai_mcp-0.1.0.dist-info/METADATA,sha256=04U52HSfVF9ODHRLU04tpkjp3m4BkllM_82EoZlvmbs,7032
|
|
6
|
+
yomemoai_mcp-0.1.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
7
|
+
yomemoai_mcp-0.1.0.dist-info/entry_points.txt,sha256=gWU6hmHA4oQMCYGqffv-f2YamGj-ERq8np2uuCSOhuI,137
|
|
8
|
+
yomemoai_mcp-0.1.0.dist-info/licenses/LICENSE,sha256=UVt2r_C3iy7rNKJAj_EcLcmcZdXONxJ01oJNsIEqTfw,1066
|
|
9
|
+
yomemoai_mcp-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 yomemo.ai
|
|
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.
|