iflow-mcp_yugabyte-yugabytedb-mcp-server 1.0.3__py3-none-any.whl → 1.0.4__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: iflow-mcp_yugabyte-yugabytedb-mcp-server
3
- Version: 1.0.3
3
+ Version: 1.0.4
4
4
  Summary: Add your description here
5
5
  Requires-Python: >=3.10
6
6
  Description-Content-Type: text/markdown
@@ -0,0 +1,7 @@
1
+ server.py,sha256=ZDllYa-YCwuY6GUFIksIu6vx6Up1vnTQy-mn1Ig8qDo,9512
2
+ iflow_mcp_yugabyte_yugabytedb_mcp_server-1.0.4.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
3
+ iflow_mcp_yugabyte_yugabytedb_mcp_server-1.0.4.dist-info/METADATA,sha256=uNufOUEnt__eFhRmn7XTEaHPZlTEJEFVi7F4g-LpoKo,9655
4
+ iflow_mcp_yugabyte_yugabytedb_mcp_server-1.0.4.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
5
+ iflow_mcp_yugabyte_yugabytedb_mcp_server-1.0.4.dist-info/entry_points.txt,sha256=0qR8G3C-z5Jb99iC45ysBZsnVGYgPefWGinP2Bhq9hE,54
6
+ iflow_mcp_yugabyte_yugabytedb_mcp_server-1.0.4.dist-info/top_level.txt,sha256=StKOSmRhvWS5IPcvhsDRbtxUTEofJgYFGOu5AAJdSWo,7
7
+ iflow_mcp_yugabyte_yugabytedb_mcp_server-1.0.4.dist-info/RECORD,,
server.py CHANGED
@@ -13,6 +13,9 @@ from fastapi import FastAPI
13
13
  from starlette.responses import JSONResponse
14
14
  import boto3
15
15
 
16
+ # Global config variable
17
+ CONFIG: ServerConfig | None = None
18
+
16
19
  @dataclass
17
20
  class AppContext:
18
21
  conn: psycopg2.extensions.connection | None = None
@@ -42,13 +45,13 @@ def normalize_pem(pem: str) -> str:
42
45
  return pem + "\n"
43
46
 
44
47
 
45
- def write_root_cert(config: ServerConfig):
46
- if not config.ssl_root_cert_secret_arn:
48
+ def write_root_cert():
49
+ if not CONFIG or not CONFIG.ssl_root_cert_secret_arn:
47
50
  return None
48
51
 
49
52
  try:
50
- sm = boto3.client("secretsmanager", region_name=config.ssl_root_cert_secret_region)
51
- resp = sm.get_secret_value(SecretId=config.ssl_root_cert_secret_arn)
53
+ sm = boto3.client("secretsmanager", region_name=CONFIG.ssl_root_cert_secret_region)
54
+ resp = sm.get_secret_value(SecretId=CONFIG.ssl_root_cert_secret_arn)
52
55
  secret_string = resp["SecretString"]
53
56
 
54
57
  # If raw PEM, just use it
@@ -57,10 +60,10 @@ def write_root_cert(config: ServerConfig):
57
60
  else:
58
61
  data = json.loads(secret_string)
59
62
 
60
- if config.ssl_root_cert_key:
61
- if config.ssl_root_cert_key not in data:
62
- raise RuntimeError(f"Certificate key '{config.ssl_root_cert_key}' not found in secret")
63
- pem = data[config.ssl_root_cert_key]
63
+ if CONFIG.ssl_root_cert_key:
64
+ if CONFIG.ssl_root_cert_key not in data:
65
+ raise RuntimeError(f"Certificate key '{CONFIG.ssl_root_cert_key}' not found in secret")
66
+ pem = data[CONFIG.ssl_root_cert_key]
64
67
  else:
65
68
  # Backward-compatible: allow exactly one entry
66
69
  if len(data) != 1:
@@ -70,10 +73,10 @@ def write_root_cert(config: ServerConfig):
70
73
  pem = next(iter(data.values()))
71
74
 
72
75
  pem = normalize_pem(pem)
73
- with open(config.ssl_root_cert_path, "w") as f:
76
+ with open(CONFIG.ssl_root_cert_path, "w") as f:
74
77
  f.write(pem.strip() + "\n")
75
78
 
76
- return config.ssl_root_cert_path
79
+ return CONFIG.ssl_root_cert_path
77
80
 
78
81
  except Exception as e:
79
82
  print(f"Failed to load root cert from Secrets Manager: {e}", file=sys.stderr)
@@ -81,16 +84,17 @@ def write_root_cert(config: ServerConfig):
81
84
 
82
85
 
83
86
  @asynccontextmanager
84
- async def app_lifespan(server: FastMCP, config: ServerConfig) -> AsyncIterator[AppContext]:
87
+ async def app_lifespan(server: FastMCP) -> AsyncIterator[AppContext]:
88
+ global CONFIG
85
89
  # Skip database connection for testing if YUGABYTEDB_URL is not set
86
- if not config.yugabytedb_url:
90
+ if not CONFIG or not CONFIG.yugabytedb_url:
87
91
  print("YUGABYTEDB_URL is not set, running in demo mode without database connection", file=sys.stderr)
88
92
  yield AppContext(conn=None)
89
93
  return
90
94
 
91
95
  print("Connecting to database...", file=sys.stderr)
92
- database_url = config.yugabytedb_url
93
- cert_path = write_root_cert(config)
96
+ database_url = CONFIG.yugabytedb_url
97
+ cert_path = write_root_cert()
94
98
  if cert_path and "sslrootcert" not in database_url:
95
99
  database_url += f" sslrootcert={cert_path}"
96
100
  conn = psycopg2.connect(database_url)
@@ -106,8 +110,6 @@ def summarize_database(ctx: Context, schema: str = "public") -> List[Dict[str, A
106
110
  Summarize the database: list tables with schema and row counts.
107
111
  """
108
112
  summary = []
109
- # Get config from context
110
- config = ctx.request_context.lifespan_context.config
111
113
  conn = ctx.request_context.lifespan_context.conn
112
114
 
113
115
  # If no database connection, return demo data
@@ -227,13 +229,13 @@ def parse_config() -> ServerConfig:
227
229
 
228
230
 
229
231
  class YugabyteDBMCPServer:
230
- def __init__(self, config: ServerConfig):
231
- self.config = config
232
+ def __init__(self):
233
+ global CONFIG
232
234
  self.mcp = FastMCP(
233
235
  "yugabytedb-mcp",
234
- lifespan=lambda server: app_lifespan(server, config),
236
+ lifespan=app_lifespan,
235
237
  json_response=True,
236
- stateless_http=config.stateless_http,
238
+ stateless_http=CONFIG.stateless_http if CONFIG else False,
237
239
  )
238
240
 
239
241
  self._register_tools()
@@ -243,7 +245,7 @@ class YugabyteDBMCPServer:
243
245
  self.mcp.add_tool(run_read_only_query)
244
246
 
245
247
  def run(self, host="0.0.0.0", port=8000):
246
- if self.config.transport == "http":
248
+ if CONFIG and CONFIG.transport == "http":
247
249
  self._run_http(host, port)
248
250
  else:
249
251
  self.mcp.run(transport="stdio")
@@ -268,11 +270,12 @@ class YugabyteDBMCPServer:
268
270
 
269
271
  if __name__ == "__main__":
270
272
  CONFIG = parse_config()
271
- server = YugabyteDBMCPServer(CONFIG)
273
+ server = YugabyteDBMCPServer()
272
274
  server.run()
273
275
 
274
276
 
275
277
  def main():
278
+ global CONFIG
276
279
  CONFIG = parse_config()
277
- server = YugabyteDBMCPServer(CONFIG)
280
+ server = YugabyteDBMCPServer()
278
281
  server.run()
@@ -1,7 +0,0 @@
1
- server.py,sha256=bc2juN3YT-P6yla0kglOyxeEAvpM4mcAqz_ySgUzwDc,9567
2
- iflow_mcp_yugabyte_yugabytedb_mcp_server-1.0.3.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
3
- iflow_mcp_yugabyte_yugabytedb_mcp_server-1.0.3.dist-info/METADATA,sha256=RHm9yfD5pPEv1VWSW4RinmmfCxSY9hy-vVxCbDI7bqY,9655
4
- iflow_mcp_yugabyte_yugabytedb_mcp_server-1.0.3.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
5
- iflow_mcp_yugabyte_yugabytedb_mcp_server-1.0.3.dist-info/entry_points.txt,sha256=0qR8G3C-z5Jb99iC45ysBZsnVGYgPefWGinP2Bhq9hE,54
6
- iflow_mcp_yugabyte_yugabytedb_mcp_server-1.0.3.dist-info/top_level.txt,sha256=StKOSmRhvWS5IPcvhsDRbtxUTEofJgYFGOu5AAJdSWo,7
7
- iflow_mcp_yugabyte_yugabytedb_mcp_server-1.0.3.dist-info/RECORD,,