Googolplexic commited on
Commit
79b56df
·
2 Parent(s): 1326e49 eb40d09

Merge branch 'tweaks'

Browse files
Files changed (4) hide show
  1. api_client.py +0 -1
  2. api_monitor.py +72 -50
  3. main.py → app.py +3 -3
  4. requirements.txt +1 -0
api_client.py CHANGED
@@ -1,6 +1,5 @@
1
  import requests
2
  import json
3
- import psycopg2
4
 
5
 
6
  def parse_key_value_string(key_value_string):
 
1
  import requests
2
  import json
 
3
 
4
 
5
  def parse_key_value_string(key_value_string):
api_monitor.py CHANGED
@@ -10,6 +10,7 @@ from dotenv import load_dotenv
10
  from apscheduler.schedulers.asyncio import AsyncIOScheduler
11
  import requests
12
 
 
13
 
14
  # Load environment variables from .env file
15
  load_dotenv(override=True)
@@ -25,11 +26,18 @@ def connect_to_db():
25
  raise ValueError(
26
  "Database password not found in environment variables. Please set DB_PASSWORD."
27
  )
 
 
 
 
 
 
 
28
  return psycopg2.connect(
29
- host="aws-0-us-west-1.pooler.supabase.com",
30
- port=6543,
31
- database="postgres",
32
- user="postgres.rivuplskngyevyzlshuh",
33
  password=db_password,
34
  cursor_factory=psycopg2.extras.DictCursor,
35
  )
@@ -89,7 +97,7 @@ def validate_api_configuration(
89
  additional_params,
90
  schedule_interval_minutes,
91
  stop_after_hours,
92
- start_at,
93
  ):
94
  """
95
  TOOL: Validate and store API configuration for monitoring.
@@ -101,6 +109,10 @@ def validate_api_configuration(
101
  before proceeding to activate_monitoring(). The API call may return success=True but contain
102
  error messages (like "401 Unauthorized", "Invalid API key", etc.) in the sample_response.
103
 
 
 
 
 
104
  WORKFLOW:
105
  1. Call this function to validate API configuration
106
  2. If success=False: Fix parameters and retry this function
@@ -108,7 +120,7 @@ def validate_api_configuration(
108
  4. If sample_response contains error messages: Fix API parameters and retry validation
109
  5. If sample_response looks valid: Use config_id in activate_monitoring() to activate monitoring
110
 
111
- Parameters:
112
  - mcp_api_key: MCP API key serves as user identifier
113
  - name: User-friendly name for the monitoring task
114
  - description: Description of what is being monitored
@@ -117,11 +129,16 @@ def validate_api_configuration(
117
  - endpoint: The specific API endpoint
118
  - param_keys_values: Parameter key-value pairs, one per line
119
  - header_keys_values: Header key-value pairs, one per line
120
- - additional_params: Optional JSON string for complex parameters - schedule_interval_minutes: Minutes between calls
 
121
  - stop_after_hours: Hours after which to stop (supports decimals, max 168 = 1 week)
122
- - start_at: When to start the monitoring (datetime string or None for immediate)
 
 
123
 
124
- Input Examples: 1. Simple GET request to monitor stock price:
 
 
125
  mcp_api_key: "your_mcp_key_here"
126
  name: "NVDA Stock Price"
127
  description: "Monitor NVIDIA stock price every 30 minutes"
@@ -135,18 +152,18 @@ def validate_api_configuration(
135
  stop_after_hours: 1.5
136
  start_at: ""
137
 
138
- 2. API with complex parameters:
139
  mcp_api_key: "your_mcp_key_here"
140
- name: "Weather Alert Monitor"
141
- description: "Monitor severe weather alerts"
142
- method: "POST"
143
- base_url: "https://api.weather.com"
144
- endpoint: "alerts"
145
- param_keys_values: "lat: 40.7128\nlon: -74.0060"
146
- header_keys_values: "X-API-Key: weather_key\nContent-Type: application/json"
147
- additional_params: '{"severity": ["severe", "extreme"], "types": ["tornado", "hurricane"]}'
148
- schedule_interval_minutes: 15
149
- stop_after_hours: 0.75
150
  start_at: "2024-06-15 09:00:00"
151
 
152
  Returns:
@@ -160,7 +177,8 @@ def validate_api_configuration(
160
  "sample_response": {...},
161
  "stop_at": "2025-06-11T12:00:00Z",
162
  "start_at": "2025-06-04T12:00:00Z"
163
- } NEXT STEP: If success=True, call activate_monitoring(config_id, mcp_api_key) to activate monitoring
 
164
  """
165
  try:
166
  # Validate input parameters
@@ -357,7 +375,7 @@ async def activate_monitoring(config_id, mcp_api_key):
357
  2. If validation successful, call this function with the config_id
358
  3. Monitoring will run automatically according to the validated schedule
359
 
360
- Parameters:
361
  - config_id: The ID from successful validate_api_configuration() execution (required)
362
  - mcp_api_key: User's MCP API key for verification (must match validation step)
363
 
@@ -465,26 +483,6 @@ async def activate_monitoring(config_id, mcp_api_key):
465
  print(
466
  f"Executing API monitoring job for {name} at {now.isoformat()}. Next call at {next_call.isoformat()}"
467
  )
468
- # If the current time is past the stop time, do not execute the job but set is_active to False
469
- if now > stop_at:
470
- print(
471
- f"Stopping API monitoring job for {name} as the stop time has been reached."
472
- )
473
- try:
474
- job_conn = connect_to_db()
475
- job_cur = job_conn.cursor()
476
- job_cur.execute(
477
- """
478
- UPDATE api_configurations SET is_active = %s WHERE config_id = %s
479
- """,
480
- (False, config_id),
481
- )
482
- job_conn.commit()
483
- job_cur.close()
484
- job_conn.close()
485
- except Exception as db_exc:
486
- print(f"Failed to update configuration status: {db_exc}")
487
- return # Stop the job if the time has passed
488
 
489
  try:
490
  # Extract API configuration parameters
@@ -552,13 +550,32 @@ async def activate_monitoring(config_id, mcp_api_key):
552
  job_cur = job_conn.cursor()
553
 
554
  # Mark config as active (only once, on first run)
555
- job_cur.execute(
556
- """
557
- UPDATE api_configurations SET is_active = %s WHERE config_id = %s
558
- """,
559
- (True, config_id),
 
 
 
 
 
 
 
 
560
  )
561
- print(f"Marked configuration {config_id} as active.")
 
 
 
 
 
 
 
 
 
 
 
562
 
563
  # Insert the actual API call result
564
  job_cur.execute(
@@ -655,7 +672,9 @@ def retrieve_monitored_data(config_id, mcp_api_key, mode="summary"):
655
 
656
  PREREQUISITE: Must call validate_api_configuration() first and obtain a config_id from successful validation, then activate_monitoring() to start monitoring.
657
 
658
- This function can be called at any time after monitoring activation to retrieve the latest data collected by the monitoring system. Parameters:
 
 
659
  - config_id: The ID of the API configuration to retrieve data for (required)
660
  - mcp_api_key: User's MCP API key for verification (must match validation step)
661
  - mode: Data return mode - "summary" (LLM-optimized), "details" (full responses, minimal metadata), "full" (everything)
@@ -667,7 +686,9 @@ def retrieve_monitored_data(config_id, mcp_api_key, mode="summary"):
667
 
668
  2. Retrieve data for weather alerts:
669
  config_id: 987654321
670
- mcp_api_key: "your_mcp_key_here" Returns:
 
 
671
  - Dictionary with monitoring status in one of three formats based on mode parameter
672
 
673
  SUMMARY mode (LLM-optimized, default):
@@ -957,6 +978,7 @@ import asyncio
957
 
958
 
959
  async def main():
 
960
  validation_response = validate_api_configuration(
961
  mcp_api_key=os.getenv("MCP_API_KEY"),
962
  name="Dog Facts API",
 
10
  from apscheduler.schedulers.asyncio import AsyncIOScheduler
11
  import requests
12
 
13
+ from apscheduler.schedulers.blocking import BlockingScheduler
14
 
15
  # Load environment variables from .env file
16
  load_dotenv(override=True)
 
26
  raise ValueError(
27
  "Database password not found in environment variables. Please set DB_PASSWORD."
28
  )
29
+
30
+ # Get database connection details from environment variables with defaults
31
+ db_host = os.getenv("DB_HOST")
32
+ db_port = int(os.getenv("DB_PORT"))
33
+ db_name = os.getenv("DB_NAME")
34
+ db_user = os.getenv("DB_USER")
35
+
36
  return psycopg2.connect(
37
+ host=db_host,
38
+ port=db_port,
39
+ database=db_name,
40
+ user=db_user,
41
  password=db_password,
42
  cursor_factory=psycopg2.extras.DictCursor,
43
  )
 
97
  additional_params,
98
  schedule_interval_minutes,
99
  stop_after_hours,
100
+ start_at, # IMPORTANT: Use empty string "" for immediate start (most common case)
101
  ):
102
  """
103
  TOOL: Validate and store API configuration for monitoring.
 
109
  before proceeding to activate_monitoring(). The API call may return success=True but contain
110
  error messages (like "401 Unauthorized", "Invalid API key", etc.) in the sample_response.
111
 
112
+ CRITICAL: Always try to add parameters that will limit the API response to a manageable size.
113
+
114
+ CRITICAL: Be sure to always clearly inform the user of the config_id after a desired validation result.
115
+
116
  WORKFLOW:
117
  1. Call this function to validate API configuration
118
  2. If success=False: Fix parameters and retry this function
 
120
  4. If sample_response contains error messages: Fix API parameters and retry validation
121
  5. If sample_response looks valid: Use config_id in activate_monitoring() to activate monitoring
122
 
123
+ ARGUMENTS:
124
  - mcp_api_key: MCP API key serves as user identifier
125
  - name: User-friendly name for the monitoring task
126
  - description: Description of what is being monitored
 
129
  - endpoint: The specific API endpoint
130
  - param_keys_values: Parameter key-value pairs, one per line
131
  - header_keys_values: Header key-value pairs, one per line
132
+ - additional_params: Optional JSON string for complex parameters
133
+ - schedule_interval_minutes: Minutes between calls
134
  - stop_after_hours: Hours after which to stop (supports decimals, max 168 = 1 week)
135
+ - start_at: Optional datetime string for when to start the monitoring.
136
+
137
+ IMPORTANT: Leave as empty string "" for immediate start (most common use case, always default to this if no start time provided). Only provide a datetime string (e.g., "2024-06-15 09:00:00") if you need to schedule monitoring for a specific future time.
138
 
139
+ Input Examples:
140
+
141
+ 1. Simple GET request to monitor stock price:
142
  mcp_api_key: "your_mcp_key_here"
143
  name: "NVDA Stock Price"
144
  description: "Monitor NVIDIA stock price every 30 minutes"
 
152
  stop_after_hours: 1.5
153
  start_at: ""
154
 
155
+ 2. Weather monitoring with free API:
156
  mcp_api_key: "your_mcp_key_here"
157
+ name: "Weather Monitor"
158
+ description: "Monitor current weather conditions every 2 hours for one week using Open-Meteo free API"
159
+ method: "GET"
160
+ base_url: "https://api.open-meteo.com"
161
+ endpoint: "v1/forecast"
162
+ param_keys_values: "latitude: 40.7128\nlongitude: -74.0060\ncurrent: temperature_2m,relative_humidity_2m,weather_code,wind_speed_10m\ntimezone: America/New_York"
163
+ header_keys_values: "Content-Type: application/json"
164
+ additional_params: "{}"
165
+ schedule_interval_minutes: 120
166
+ stop_after_hours: 168
167
  start_at: "2024-06-15 09:00:00"
168
 
169
  Returns:
 
177
  "sample_response": {...},
178
  "stop_at": "2025-06-11T12:00:00Z",
179
  "start_at": "2025-06-04T12:00:00Z"
180
+ }
181
+ NEXT STEP: If success=True, call activate_monitoring(config_id, mcp_api_key) to activate monitoring
182
  """
183
  try:
184
  # Validate input parameters
 
375
  2. If validation successful, call this function with the config_id
376
  3. Monitoring will run automatically according to the validated schedule
377
 
378
+ ARGUMENTS:
379
  - config_id: The ID from successful validate_api_configuration() execution (required)
380
  - mcp_api_key: User's MCP API key for verification (must match validation step)
381
 
 
483
  print(
484
  f"Executing API monitoring job for {name} at {now.isoformat()}. Next call at {next_call.isoformat()}"
485
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
486
 
487
  try:
488
  # Extract API configuration parameters
 
550
  job_cur = job_conn.cursor()
551
 
552
  # Mark config as active (only once, on first run)
553
+ if not config["is_active"]:
554
+ job_cur.execute(
555
+ """
556
+ UPDATE api_configurations SET is_active = %s WHERE config_id = %s
557
+ """,
558
+ (True, config_id),
559
+ )
560
+ print(f"Marked configuration {config_id} as active.")
561
+
562
+ # Check if this is the last call by comparing current time to stop_at
563
+ current_time = datetime.now()
564
+ next_call_time = current_time + timedelta(
565
+ minutes=schedule_interval_minutes
566
  )
567
+
568
+ if next_call_time >= stop_at:
569
+ # This is the last call, mark as inactive
570
+ job_cur.execute(
571
+ """
572
+ UPDATE api_configurations SET is_active = %s WHERE config_id = %s
573
+ """,
574
+ (False, config_id),
575
+ )
576
+ print(
577
+ f"Last call for configuration {config_id}. Marked as inactive."
578
+ )
579
 
580
  # Insert the actual API call result
581
  job_cur.execute(
 
672
 
673
  PREREQUISITE: Must call validate_api_configuration() first and obtain a config_id from successful validation, then activate_monitoring() to start monitoring.
674
 
675
+ This function can be called at any time after monitoring activation to retrieve the latest data collected by the monitoring system.
676
+
677
+ ARGUMENTS:
678
  - config_id: The ID of the API configuration to retrieve data for (required)
679
  - mcp_api_key: User's MCP API key for verification (must match validation step)
680
  - mode: Data return mode - "summary" (LLM-optimized), "details" (full responses, minimal metadata), "full" (everything)
 
686
 
687
  2. Retrieve data for weather alerts:
688
  config_id: 987654321
689
+ mcp_api_key: "your_mcp_key_here"
690
+
691
+ Returns:
692
  - Dictionary with monitoring status in one of three formats based on mode parameter
693
 
694
  SUMMARY mode (LLM-optimized, default):
 
978
 
979
 
980
  async def main():
981
+
982
  validation_response = validate_api_configuration(
983
  mcp_api_key=os.getenv("MCP_API_KEY"),
984
  name="Dog Facts API",
main.py → app.py RENAMED
@@ -41,14 +41,14 @@ validation_tab = gr.Interface(
41
  value="{}",
42
  ),
43
  gr.Number(
44
- label="Schedule Interval (minutes)", value=20, minimum=1, maximum=1440
45
  ),
46
  gr.Number(
47
  label="Stop After (hours)", value=24, minimum=0.1, maximum=168, step=0.1
48
  ),
49
  gr.Textbox(
50
- label="Start Time (optional)",
51
- placeholder="YYYY-MM-DD HH:MM:SS or leave empty for immediate start",
52
  value="",
53
  ),
54
  ],
 
41
  value="{}",
42
  ),
43
  gr.Number(
44
+ label="Schedule Interval (minutes)", value=20, minimum=0.1, maximum=1440
45
  ),
46
  gr.Number(
47
  label="Stop After (hours)", value=24, minimum=0.1, maximum=168, step=0.1
48
  ),
49
  gr.Textbox(
50
+ label="Start Time (optional - leave empty for immediate start)",
51
+ placeholder="Leave empty for immediate start, or enter YYYY-MM-DD HH:MM:SS for scheduled start",
52
  value="",
53
  ),
54
  ],
requirements.txt CHANGED
@@ -62,3 +62,4 @@ tzlocal==5.3.1
62
  urllib3==2.4.0
63
  uvicorn==0.34.3
64
  websockets==15.0.1
 
 
62
  urllib3==2.4.0
63
  uvicorn==0.34.3
64
  websockets==15.0.1
65
+ apscheduler==3.11.0