mcp-sqlite-memory-bank 1.5.1__py3-none-any.whl → 1.6.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.
- mcp_sqlite_memory_bank/__init__.py +3 -3
- mcp_sqlite_memory_bank/__main__.py +8 -7
- mcp_sqlite_memory_bank/database.py +166 -48
- mcp_sqlite_memory_bank/prompts.py +64 -48
- mcp_sqlite_memory_bank/resources.py +218 -144
- mcp_sqlite_memory_bank/semantic.py +25 -13
- mcp_sqlite_memory_bank/server.py +174 -32
- mcp_sqlite_memory_bank/tools/__init__.py +26 -29
- mcp_sqlite_memory_bank/tools/analytics.py +179 -130
- mcp_sqlite_memory_bank/tools/basic.py +417 -4
- mcp_sqlite_memory_bank/tools/discovery.py +549 -360
- mcp_sqlite_memory_bank/tools/search.py +147 -71
- mcp_sqlite_memory_bank/types.py +6 -1
- mcp_sqlite_memory_bank/utils.py +154 -105
- {mcp_sqlite_memory_bank-1.5.1.dist-info → mcp_sqlite_memory_bank-1.6.2.dist-info}/METADATA +54 -6
- mcp_sqlite_memory_bank-1.6.2.dist-info/RECORD +21 -0
- mcp_sqlite_memory_bank-1.5.1.dist-info/RECORD +0 -21
- {mcp_sqlite_memory_bank-1.5.1.dist-info → mcp_sqlite_memory_bank-1.6.2.dist-info}/WHEEL +0 -0
- {mcp_sqlite_memory_bank-1.5.1.dist-info → mcp_sqlite_memory_bank-1.6.2.dist-info}/entry_points.txt +0 -0
- {mcp_sqlite_memory_bank-1.5.1.dist-info → mcp_sqlite_memory_bank-1.6.2.dist-info}/licenses/LICENSE +0 -0
- {mcp_sqlite_memory_bank-1.5.1.dist-info → mcp_sqlite_memory_bank-1.6.2.dist-info}/top_level.txt +0 -0
@@ -19,26 +19,28 @@ import json
|
|
19
19
|
|
20
20
|
class MemoryBankPrompts:
|
21
21
|
"""Manages MCP Prompts for the SQLite Memory Bank."""
|
22
|
-
|
22
|
+
|
23
23
|
def __init__(self, mcp_app: FastMCP, db_path: str):
|
24
24
|
self.mcp = mcp_app
|
25
25
|
self.db_path = db_path
|
26
26
|
self._register_prompts()
|
27
|
-
|
27
|
+
|
28
28
|
def _register_prompts(self):
|
29
29
|
"""Register MCP prompts with the FastMCP app."""
|
30
|
-
|
30
|
+
|
31
31
|
@self.mcp.prompt("analyze-memory-content")
|
32
32
|
async def analyze_memory_content(table_name: Optional[str] = None) -> str:
|
33
33
|
"""Analyze memory bank content and provide insights."""
|
34
34
|
db = get_database(self.db_path)
|
35
|
-
|
35
|
+
|
36
36
|
if table_name:
|
37
37
|
# Analyze specific table
|
38
38
|
result = cast(Dict[str, Any], db.read_rows(table_name, {}))
|
39
39
|
if not result.get("success"):
|
40
|
-
return
|
41
|
-
|
40
|
+
return (
|
41
|
+
f"Error: Could not access table '{table_name}'. Please check if it exists."
|
42
|
+
)
|
43
|
+
|
42
44
|
rows = result.get("rows", [])
|
43
45
|
prompt = f"""Please analyze the content in the '{table_name}' table from the memory bank.
|
44
46
|
|
@@ -58,21 +60,23 @@ Focus on actionable insights that could help improve how this information is sto
|
|
58
60
|
tables_result = cast(Dict[str, Any], db.list_tables())
|
59
61
|
if not tables_result.get("success"):
|
60
62
|
return "Error: Could not access memory bank tables."
|
61
|
-
|
63
|
+
|
62
64
|
tables = tables_result.get("tables", [])
|
63
65
|
overview = {"tables": len(tables), "total_content": []}
|
64
|
-
|
66
|
+
|
65
67
|
for table in tables[:5]: # Limit to first 5 tables
|
66
68
|
rows_result = cast(Dict[str, Any], db.read_rows(table, {}))
|
67
69
|
if rows_result.get("success"):
|
68
70
|
rows = rows_result.get("rows", [])
|
69
71
|
total_content = cast(List[Any], overview["total_content"])
|
70
|
-
total_content.append(
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
72
|
+
total_content.append(
|
73
|
+
{
|
74
|
+
"table": table,
|
75
|
+
"rows": len(rows),
|
76
|
+
"sample": rows[:2] if rows else [],
|
77
|
+
}
|
78
|
+
)
|
79
|
+
|
76
80
|
prompt = f"""Please analyze the overall content in this memory bank.
|
77
81
|
|
78
82
|
Memory Bank Overview:
|
@@ -85,31 +89,35 @@ Please provide:
|
|
85
89
|
4. Suggestions for leveraging this content more effectively
|
86
90
|
|
87
91
|
Focus on high-level strategic insights about the memory bank's utility and organization."""
|
88
|
-
|
92
|
+
|
89
93
|
return prompt
|
90
|
-
|
94
|
+
|
91
95
|
@self.mcp.prompt("search-and-summarize")
|
92
96
|
async def search_and_summarize(query: str, max_results: Optional[int] = 10) -> str:
|
93
97
|
"""Search memory content and create a summary prompt."""
|
94
98
|
db = get_database(self.db_path)
|
95
|
-
|
99
|
+
|
96
100
|
# Perform search
|
97
101
|
result = cast(Dict[str, Any], db.search_content(query, None, max_results or 10))
|
98
102
|
if not result.get("success"):
|
99
|
-
return
|
100
|
-
|
103
|
+
return (
|
104
|
+
f"Error: Could not search for '{query}'. {result.get('error', 'Unknown error')}"
|
105
|
+
)
|
106
|
+
|
101
107
|
search_results = result.get("results", [])
|
102
108
|
if not search_results:
|
103
109
|
return f"No results found for query: '{query}'. Please try different search terms or check if relevant content exists in the memory bank."
|
104
|
-
|
110
|
+
|
105
111
|
# Format results for prompt
|
106
112
|
formatted_results = []
|
107
|
-
for i, result in enumerate(search_results[:max_results or 10], 1):
|
113
|
+
for i, result in enumerate(search_results[: max_results or 10], 1):
|
108
114
|
formatted_results.append(f"{i}. Table: {result.get('table', 'unknown')}")
|
109
|
-
formatted_results.append(
|
115
|
+
formatted_results.append(
|
116
|
+
f" Content: {result.get('content', 'No content')[:200]}..."
|
117
|
+
)
|
110
118
|
formatted_results.append(f" Relevance: {result.get('relevance', 'N/A')}")
|
111
119
|
formatted_results.append("")
|
112
|
-
|
120
|
+
|
113
121
|
prompt = f"""Based on the search query "{query}", here are the most relevant results from the memory bank:
|
114
122
|
|
115
123
|
Search Results:
|
@@ -122,19 +130,21 @@ Please provide:
|
|
122
130
|
4. Actionable insights based on this content
|
123
131
|
|
124
132
|
Use this information to provide a thorough, well-organized response that synthesizes the search results."""
|
125
|
-
|
133
|
+
|
126
134
|
return prompt
|
127
|
-
|
135
|
+
|
128
136
|
@self.mcp.prompt("technical-decision-analysis")
|
129
|
-
async def technical_decision_analysis(
|
137
|
+
async def technical_decision_analysis(
|
138
|
+
decision_topic: Optional[str] = None,
|
139
|
+
) -> str:
|
130
140
|
"""Analyze technical decisions from the memory bank."""
|
131
141
|
db = get_database(self.db_path)
|
132
|
-
|
142
|
+
|
133
143
|
# Try to find technical_decisions table
|
134
144
|
tables_result = cast(Dict[str, Any], db.list_tables())
|
135
145
|
if not tables_result.get("success"):
|
136
146
|
return "Error: Could not access memory bank."
|
137
|
-
|
147
|
+
|
138
148
|
tables = tables_result.get("tables", [])
|
139
149
|
if "technical_decisions" not in tables:
|
140
150
|
return """No technical decisions table found in the memory bank.
|
@@ -145,34 +155,40 @@ To use this prompt effectively, please:
|
|
145
155
|
3. Try this prompt again
|
146
156
|
|
147
157
|
The table should include fields like: decision_name, chosen_approach, rationale, alternatives, timestamp."""
|
148
|
-
|
158
|
+
|
149
159
|
# Get technical decisions
|
150
160
|
where_clause = {}
|
151
161
|
if decision_topic:
|
152
162
|
# This is a simplified search - in practice you'd want semantic search
|
153
163
|
where_clause = {"decision_name": decision_topic}
|
154
|
-
|
164
|
+
|
155
165
|
result = db.read_rows("technical_decisions", where_clause)
|
156
166
|
if not result.get("success"):
|
157
167
|
return "Error: Could not read technical decisions."
|
158
|
-
|
168
|
+
|
159
169
|
decisions = result.get("rows", [])
|
160
170
|
if not decisions:
|
161
171
|
topic_msg = f" related to '{decision_topic}'" if decision_topic else ""
|
162
172
|
return f"No technical decisions found{topic_msg}. Consider adding some decisions to the memory bank first."
|
163
|
-
|
173
|
+
|
164
174
|
# Format decisions for analysis
|
165
175
|
formatted_decisions = []
|
166
176
|
decisions_list = cast(List[Dict[str, Any]], decisions)
|
167
177
|
for i, decision in enumerate(decisions_list, 1):
|
168
|
-
formatted_decisions.append(
|
169
|
-
|
170
|
-
|
171
|
-
|
178
|
+
formatted_decisions.append(
|
179
|
+
f"{i}. Decision: {decision.get('decision_name', 'Unknown')}"
|
180
|
+
)
|
181
|
+
formatted_decisions.append(
|
182
|
+
f" Approach: {decision.get('chosen_approach', 'Not specified')}"
|
183
|
+
)
|
184
|
+
formatted_decisions.append(
|
185
|
+
f" Rationale: {decision.get('rationale', 'Not provided')}"
|
186
|
+
)
|
187
|
+
if decision.get("alternatives"):
|
172
188
|
formatted_decisions.append(f" Alternatives: {decision.get('alternatives')}")
|
173
189
|
formatted_decisions.append(f" Date: {decision.get('timestamp', 'Unknown')}")
|
174
190
|
formatted_decisions.append("")
|
175
|
-
|
191
|
+
|
176
192
|
prompt = f"""Please analyze these technical decisions from the memory bank:
|
177
193
|
|
178
194
|
Technical Decisions{f" (filtered by: {decision_topic})" if decision_topic else ""}:
|
@@ -186,19 +202,19 @@ Please provide:
|
|
186
202
|
5. Suggestions for improving decision documentation
|
187
203
|
|
188
204
|
Focus on actionable insights that can improve technical decision-making processes."""
|
189
|
-
|
205
|
+
|
190
206
|
return prompt
|
191
|
-
|
207
|
+
|
192
208
|
@self.mcp.prompt("memory-bank-context")
|
193
209
|
async def memory_bank_context(context_type: str = "full") -> str:
|
194
210
|
"""Provide memory bank context for AI conversations."""
|
195
211
|
db = get_database(self.db_path)
|
196
|
-
|
212
|
+
|
197
213
|
# Get overview
|
198
214
|
tables_result = db.list_tables()
|
199
215
|
if not tables_result.get("success"):
|
200
216
|
return "Error: Could not access memory bank for context."
|
201
|
-
|
217
|
+
|
202
218
|
tables = tables_result.get("tables", [])
|
203
219
|
context_info = {
|
204
220
|
"available_tables": tables,
|
@@ -206,16 +222,16 @@ Focus on actionable insights that can improve technical decision-making processe
|
|
206
222
|
"Full-text search across all content",
|
207
223
|
"Semantic search (if embeddings are available)",
|
208
224
|
"Structured data queries",
|
209
|
-
"Content analytics and insights"
|
225
|
+
"Content analytics and insights",
|
210
226
|
],
|
211
227
|
"usage_suggestions": [
|
212
228
|
"Use search_content() for finding specific information",
|
213
229
|
"Use semantic_search() for conceptual queries",
|
214
230
|
"Use read_rows() for structured data access",
|
215
|
-
"Use explore_tables() to discover available content"
|
216
|
-
]
|
231
|
+
"Use explore_tables() to discover available content",
|
232
|
+
],
|
217
233
|
}
|
218
|
-
|
234
|
+
|
219
235
|
if context_type == "brief":
|
220
236
|
tables_list = cast(List[str], tables)
|
221
237
|
prompt = f"""Memory Bank Context (Brief):
|
@@ -234,11 +250,11 @@ This memory bank contains structured information that can be searched and analyz
|
|
234
250
|
rows = cast(List[Any], result.get("rows", []))
|
235
251
|
sample_content[table] = {
|
236
252
|
"row_count": len(rows),
|
237
|
-
"sample_row": rows[0] if rows else None
|
253
|
+
"sample_row": rows[0] if rows else None,
|
238
254
|
}
|
239
255
|
except Exception:
|
240
256
|
continue
|
241
|
-
|
257
|
+
|
242
258
|
prompt = f"""Memory Bank Context (Full):
|
243
259
|
|
244
260
|
{json.dumps(context_info, indent=2)}
|
@@ -247,7 +263,7 @@ Sample Content:
|
|
247
263
|
{json.dumps(sample_content, indent=2)}
|
248
264
|
|
249
265
|
This memory bank contains structured information that can be searched, analyzed, and leveraged for various tasks. The content is organized in tables with different types of information. Use the available search and query tools to access specific content as needed for your current task."""
|
250
|
-
|
266
|
+
|
251
267
|
return prompt
|
252
268
|
|
253
269
|
|