Skip to content

Commit 168cac5

Browse files
authored
Merge pull request #3 from KxSystems/fix-date-formatting
fix date formatting
2 parents 64e5268 + 837f3fc commit 168cac5

File tree

5 files changed

+34
-34
lines changed

5 files changed

+34
-34
lines changed

src/mcp_server/main.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
from mcp_server.server import main
2+
3+
if __name__ == "__main__":
4+
main()

src/mcp_server/resources/kdbx_database_tables.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ async def kdbx_describe_table_impl(table: str) -> List[TextContent]:
1919
List[TextContent]: Table description with metadata and sample data
2020
"""
2121
try:
22-
conn = get_kdb_connection(config.kdbx_config)
22+
conn = get_kdb_connection()
2323

2424
total_records = conn('{count get x}', table).py()
2525

@@ -62,7 +62,7 @@ async def kdbx_describe_table_impl(table: str) -> List[TextContent]:
6262

6363
async def kdbx_describe_tables_impl() -> List[TextContent]:
6464
try:
65-
conn = get_kdb_connection(config.kdbx_config)
65+
conn = get_kdb_connection()
6666

6767
available_tables = conn.tables(None).py()
6868

src/mcp_server/server.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -215,9 +215,7 @@ def parse_args():
215215

216216

217217
def main():
218-
219218
args = parse_args()
220-
221219
# Determine transport mode (only set if CLI flag is provided)
222220
args.kdbx_mcp_transport = None
223221
if args.streamable_http:
@@ -238,6 +236,3 @@ def main():
238236

239237
server = McpServer(config)
240238
server.run()
241-
242-
if __name__ == "__main__":
243-
main()

src/mcp_server/tools/kdbx_run_sql_query.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import logging
2+
import pykx as kx
3+
import json
24
from typing import Dict, Any
3-
from mcp_server.utils.kdbx import run_kdbx_sql_query
5+
from mcp_server.utils.kdbx import get_kdb_connection
46

57
logger = logging.getLogger(__name__)
68
MAX_ROWS_RETURNED = 1000
79

8-
910
async def run_query_impl(sqlSelectQuery: str) -> Dict[str, Any]:
1011
try:
1112
dangerous_keywords = ['INSERT', 'DROP', 'DELETE', 'TRUNCATE', 'ALTER', 'CREATE']
@@ -15,15 +16,14 @@ async def run_query_impl(sqlSelectQuery: str) -> Dict[str, Any]:
1516
if keyword in query_upper and not query_upper.startswith('SELECT'):
1617
raise ValueError(f"Query contains dangerous keyword: {keyword}")
1718

18-
result = run_kdbx_sql_query(sqlSelectQuery, MAX_ROWS_RETURNED)
19+
conn = get_kdb_connection()
20+
# below query gets kdbx table data back as json for correct conversion of different datatypes
21+
result = conn('{r:.s.e x;`rowCount`data!(count r;.j.j y sublist r)}', kx.CharVector(sqlSelectQuery), MAX_ROWS_RETURNED)
1922
total = int(result['rowCount'])
20-
table = result['data'].pd()
21-
22-
if table.empty:
23+
if 0==total:
2324
return {"status": "success", "data": [], "message": "No rows returned"}
24-
25-
rows = table.to_dict(orient="records")
26-
25+
# parse json result
26+
rows = json.loads(result['data'].py().decode('utf-8'))
2727
if total > MAX_ROWS_RETURNED:
2828
logger.info(f"Table has {total} rows. Query returned truncated data to {MAX_ROWS_RETURNED} rows.")
2929
return {

src/mcp_server/utils/kdbx.py

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,24 @@
77

88
logger = logging.getLogger(__name__)
99

10+
def get_kdb_connection() -> kx.QConnection:
11+
try:
12+
conn = kdb_sync_connection(config.kdbx_config)
13+
conn('') # check if conn is live for existing connection from cache
14+
return conn
15+
except Exception as e:
16+
if "Attempted to use a closed IPC connection" in str(e):
17+
logger.warning("KDB-X connection was closed. Reinitializing...")
18+
cleanup_kdb_connection()
19+
conn = kdb_sync_connection(config.kdbx_config)
20+
conn('')
21+
return conn
22+
else:
23+
logger.error(f"Error in creating KDBX connection: {e}")
24+
raise
25+
1026
@lru_cache()
11-
def get_kdb_connection(config: Optional[KDBConfig] = None) -> kx.QConnection:
27+
def kdb_sync_connection(config: Optional[KDBConfig] = None) -> kx.QConnection:
1228
if config is None:
1329
config = default_kdb_config
1430

@@ -34,21 +50,6 @@ def get_kdb_connection(config: Optional[KDBConfig] = None) -> kx.QConnection:
3450
logger.error(f"Failed to connect to KDB")
3551
raise
3652

37-
def run_kdbx_sql_query(query:str, max_rows:int) -> any:
38-
try:
39-
conn = get_kdb_connection(config.kdbx_config)
40-
result = conn('{r:.s.e x;`rowCount`data!(count r;y sublist r)}', kx.CharVector(query), max_rows)
41-
return result
42-
except Exception as e:
43-
if "Attempted to use a closed IPC connection" in str(e):
44-
logger.warning("KDB-X connection was closed. Reinitializing...")
45-
cleanup_kdb_connection()
46-
conn = get_kdb_connection(config.kdbx_config)
47-
return conn('{r:.s.e x;`rowCount`data!(count r;y sublist r)}', kx.CharVector(query), max_rows)
48-
else:
49-
logger.error(f"Error running KDB query: {e}")
50-
raise
51-
5253
def cleanup_kdb_connection():
53-
get_kdb_connection.cache_clear()
54-
logger.info("KDB connection cache cleared")
54+
kdb_sync_connection.cache_clear()
55+
logger.info("KDBX connection cache cleared")

0 commit comments

Comments
 (0)