MindsDB 25.5.3.0__py3-none-any.whl → 25.5.4.1__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.
Potentially problematic release.
This version of MindsDB might be problematic. Click here for more details.
- mindsdb/__about__.py +8 -8
- mindsdb/__main__.py +127 -79
- mindsdb/api/a2a/__init__.py +0 -0
- mindsdb/api/a2a/__main__.py +144 -0
- mindsdb/api/a2a/agent.py +308 -0
- mindsdb/api/a2a/common/__init__.py +0 -0
- mindsdb/api/a2a/common/server/__init__.py +4 -0
- mindsdb/api/a2a/common/server/server.py +164 -0
- mindsdb/api/a2a/common/server/task_manager.py +287 -0
- mindsdb/api/a2a/common/server/utils.py +28 -0
- mindsdb/api/a2a/common/types.py +365 -0
- mindsdb/api/a2a/constants.py +9 -0
- mindsdb/api/a2a/run_a2a.py +86 -0
- mindsdb/api/a2a/task_manager.py +560 -0
- mindsdb/api/executor/command_executor.py +185 -309
- mindsdb/api/executor/datahub/classes/response.py +5 -2
- mindsdb/api/executor/datahub/datanodes/integration_datanode.py +39 -72
- mindsdb/api/executor/planner/query_planner.py +10 -1
- mindsdb/api/executor/sql_query/result_set.py +185 -52
- mindsdb/api/executor/sql_query/sql_query.py +1 -1
- mindsdb/api/executor/sql_query/steps/apply_predictor_step.py +9 -12
- mindsdb/api/executor/sql_query/steps/fetch_dataframe.py +8 -10
- mindsdb/api/executor/sql_query/steps/fetch_dataframe_partition.py +5 -44
- mindsdb/api/executor/sql_query/steps/insert_step.py +24 -15
- mindsdb/api/executor/sql_query/steps/join_step.py +1 -1
- mindsdb/api/executor/sql_query/steps/project_step.py +1 -1
- mindsdb/api/executor/sql_query/steps/sql_steps.py +1 -1
- mindsdb/api/executor/sql_query/steps/subselect_step.py +4 -8
- mindsdb/api/executor/sql_query/steps/union_step.py +1 -3
- mindsdb/api/http/initialize.py +99 -83
- mindsdb/api/http/namespaces/analysis.py +3 -3
- mindsdb/api/http/namespaces/config.py +61 -86
- mindsdb/api/http/namespaces/file.py +8 -2
- mindsdb/api/http/namespaces/sql.py +13 -27
- mindsdb/api/mcp/start.py +42 -5
- mindsdb/api/mysql/mysql_proxy/data_types/mysql_packet.py +0 -1
- mindsdb/api/mysql/mysql_proxy/data_types/mysql_packets/binary_resultset_row_package.py +52 -19
- mindsdb/api/mysql/mysql_proxy/executor/mysql_executor.py +8 -10
- mindsdb/api/mysql/mysql_proxy/libs/constants/mysql.py +54 -38
- mindsdb/api/mysql/mysql_proxy/mysql_proxy.py +82 -115
- mindsdb/api/mysql/mysql_proxy/utilities/dump.py +351 -0
- mindsdb/api/postgres/postgres_proxy/executor/executor.py +1 -1
- mindsdb/api/postgres/postgres_proxy/postgres_proxy.py +5 -6
- mindsdb/integrations/handlers/altibase_handler/altibase_handler.py +26 -27
- mindsdb/integrations/handlers/altibase_handler/connection_args.py +13 -13
- mindsdb/integrations/handlers/altibase_handler/tests/test_altibase_handler.py +8 -8
- mindsdb/integrations/handlers/altibase_handler/tests/test_altibase_handler_dsn.py +13 -13
- mindsdb/integrations/handlers/anthropic_handler/__init__.py +2 -2
- mindsdb/integrations/handlers/anthropic_handler/anthropic_handler.py +1 -3
- mindsdb/integrations/handlers/aurora_handler/aurora_handler.py +1 -0
- mindsdb/integrations/handlers/autosklearn_handler/autosklearn_handler.py +1 -1
- mindsdb/integrations/handlers/autosklearn_handler/config.py +0 -1
- mindsdb/integrations/handlers/bigquery_handler/bigquery_handler.py +1 -1
- mindsdb/integrations/handlers/bigquery_handler/tests/test_bigquery_handler.py +1 -1
- mindsdb/integrations/handlers/binance_handler/binance_handler.py +1 -0
- mindsdb/integrations/handlers/binance_handler/binance_tables.py +3 -4
- mindsdb/integrations/handlers/byom_handler/__init__.py +0 -1
- mindsdb/integrations/handlers/byom_handler/requirements.txt +1 -2
- mindsdb/integrations/handlers/ckan_handler/ckan_handler.py +3 -0
- mindsdb/integrations/handlers/clickhouse_handler/__init__.py +1 -1
- mindsdb/integrations/handlers/cloud_spanner_handler/tests/test_cloud_spanner_handler.py +0 -2
- mindsdb/integrations/handlers/cloud_sql_handler/cloud_sql_handler.py +0 -1
- mindsdb/integrations/handlers/cohere_handler/__init__.py +1 -1
- mindsdb/integrations/handlers/cohere_handler/cohere_handler.py +11 -13
- mindsdb/integrations/handlers/confluence_handler/confluence_tables.py +6 -0
- mindsdb/integrations/handlers/databend_handler/connection_args.py +1 -1
- mindsdb/integrations/handlers/databend_handler/databend_handler.py +4 -4
- mindsdb/integrations/handlers/databend_handler/tests/__init__.py +0 -1
- mindsdb/integrations/handlers/databend_handler/tests/test_databend_handler.py +1 -1
- mindsdb/integrations/handlers/derby_handler/connection_args.py +1 -1
- mindsdb/integrations/handlers/derby_handler/derby_handler.py +14 -22
- mindsdb/integrations/handlers/derby_handler/tests/test_derby_handler.py +6 -6
- mindsdb/integrations/handlers/discord_handler/discord_handler.py +5 -5
- mindsdb/integrations/handlers/discord_handler/discord_tables.py +3 -3
- mindsdb/integrations/handlers/discord_handler/tests/test_discord.py +5 -3
- mindsdb/integrations/handlers/dockerhub_handler/dockerhub.py +3 -3
- mindsdb/integrations/handlers/dockerhub_handler/dockerhub_handler.py +2 -2
- mindsdb/integrations/handlers/dockerhub_handler/dockerhub_tables.py +57 -54
- mindsdb/integrations/handlers/dremio_handler/__init__.py +2 -2
- mindsdb/integrations/handlers/druid_handler/__init__.py +1 -1
- mindsdb/integrations/handlers/druid_handler/druid_handler.py +2 -2
- mindsdb/integrations/handlers/edgelessdb_handler/tests/test_edgelessdb_handler.py +9 -9
- mindsdb/integrations/handlers/email_handler/email_client.py +1 -1
- mindsdb/integrations/handlers/email_handler/email_ingestor.py +1 -1
- mindsdb/integrations/handlers/email_handler/email_tables.py +0 -1
- mindsdb/integrations/handlers/email_handler/settings.py +0 -1
- mindsdb/integrations/handlers/eventstoredb_handler/eventstoredb_handler.py +2 -1
- mindsdb/integrations/handlers/firebird_handler/firebird_handler.py +1 -1
- mindsdb/integrations/handlers/flaml_handler/flaml_handler.py +9 -9
- mindsdb/integrations/handlers/frappe_handler/frappe_client.py +5 -5
- mindsdb/integrations/handlers/frappe_handler/frappe_handler.py +6 -5
- mindsdb/integrations/handlers/frappe_handler/frappe_tables.py +2 -2
- mindsdb/integrations/handlers/github_handler/connection_args.py +2 -2
- mindsdb/integrations/handlers/github_handler/github_handler.py +1 -8
- mindsdb/integrations/handlers/github_handler/github_tables.py +13 -24
- mindsdb/integrations/handlers/gitlab_handler/gitlab_handler.py +2 -1
- mindsdb/integrations/handlers/gitlab_handler/gitlab_tables.py +1 -4
- mindsdb/integrations/handlers/gmail_handler/gmail_handler.py +6 -13
- mindsdb/integrations/handlers/google_books_handler/google_books_handler.py +2 -1
- mindsdb/integrations/handlers/google_books_handler/google_books_tables.py +0 -3
- mindsdb/integrations/handlers/google_calendar_handler/google_calendar_handler.py +4 -4
- mindsdb/integrations/handlers/google_calendar_handler/google_calendar_tables.py +2 -6
- mindsdb/integrations/handlers/google_content_shopping_handler/google_content_shopping_handler.py +3 -2
- mindsdb/integrations/handlers/google_content_shopping_handler/google_content_shopping_tables.py +0 -3
- mindsdb/integrations/handlers/google_fit_handler/google_fit_handler.py +10 -12
- mindsdb/integrations/handlers/google_fit_handler/google_fit_tables.py +11 -13
- mindsdb/integrations/handlers/google_search_handler/google_search_handler.py +2 -1
- mindsdb/integrations/handlers/google_search_handler/google_search_tables.py +0 -3
- mindsdb/integrations/handlers/groq_handler/__init__.py +3 -3
- mindsdb/integrations/handlers/hackernews_handler/hn_handler.py +5 -7
- mindsdb/integrations/handlers/hackernews_handler/hn_table.py +6 -7
- mindsdb/integrations/handlers/hive_handler/tests/test_hive_handler.py +1 -1
- mindsdb/integrations/handlers/hsqldb_handler/connection_args.py +6 -6
- mindsdb/integrations/handlers/hsqldb_handler/hsqldb_handler.py +4 -3
- mindsdb/integrations/handlers/huggingface_api_handler/exceptions.py +1 -1
- mindsdb/integrations/handlers/huggingface_api_handler/huggingface_api_handler.py +1 -8
- mindsdb/integrations/handlers/huggingface_handler/huggingface_handler.py +6 -6
- mindsdb/integrations/handlers/huggingface_handler/requirements.txt +1 -1
- mindsdb/integrations/handlers/huggingface_handler/requirements_cpu.txt +1 -1
- mindsdb/integrations/handlers/ignite_handler/ignite_handler.py +2 -1
- mindsdb/integrations/handlers/impala_handler/impala_handler.py +9 -12
- mindsdb/integrations/handlers/impala_handler/tests/test_impala_handler.py +11 -11
- mindsdb/integrations/handlers/influxdb_handler/influxdb_handler.py +10 -13
- mindsdb/integrations/handlers/influxdb_handler/influxdb_tables.py +20 -20
- mindsdb/integrations/handlers/informix_handler/__about__.py +8 -8
- mindsdb/integrations/handlers/informix_handler/__init__.py +12 -5
- mindsdb/integrations/handlers/informix_handler/informix_handler.py +99 -133
- mindsdb/integrations/handlers/informix_handler/tests/test_informix_handler.py +13 -11
- mindsdb/integrations/handlers/ingres_handler/__about__.py +0 -1
- mindsdb/integrations/handlers/ingres_handler/ingres_handler.py +1 -0
- mindsdb/integrations/handlers/jira_handler/jira_handler.py +4 -4
- mindsdb/integrations/handlers/jira_handler/jira_tables.py +9 -9
- mindsdb/integrations/handlers/kinetica_handler/__init__.py +0 -1
- mindsdb/integrations/handlers/lancedb_handler/requirements.txt +0 -1
- mindsdb/integrations/handlers/langchain_handler/langchain_handler.py +4 -4
- mindsdb/integrations/handlers/langchain_handler/tools.py +9 -10
- mindsdb/integrations/handlers/leonardoai_handler/__init__.py +1 -1
- mindsdb/integrations/handlers/lightwood_handler/functions.py +2 -2
- mindsdb/integrations/handlers/lightwood_handler/lightwood_handler.py +0 -1
- mindsdb/integrations/handlers/lightwood_handler/tests/test_lightwood_handler.py +11 -11
- mindsdb/integrations/handlers/litellm_handler/litellm_handler.py +37 -20
- mindsdb/integrations/handlers/llama_index_handler/llama_index_handler.py +4 -4
- mindsdb/integrations/handlers/llama_index_handler/settings.py +10 -9
- mindsdb/integrations/handlers/materialize_handler/tests/test_materialize_handler.py +8 -10
- mindsdb/integrations/handlers/matrixone_handler/matrixone_handler.py +4 -4
- mindsdb/integrations/handlers/matrixone_handler/tests/test_matrixone_handler.py +8 -9
- mindsdb/integrations/handlers/maxdb_handler/connection_args.py +25 -25
- mindsdb/integrations/handlers/maxdb_handler/maxdb_handler.py +1 -0
- mindsdb/integrations/handlers/mediawiki_handler/mediawiki_handler.py +3 -2
- mindsdb/integrations/handlers/mediawiki_handler/mediawiki_tables.py +1 -1
- mindsdb/integrations/handlers/mendeley_handler/__about__.py +1 -1
- mindsdb/integrations/handlers/mendeley_handler/__init__.py +2 -2
- mindsdb/integrations/handlers/mendeley_handler/mendeley_handler.py +48 -56
- mindsdb/integrations/handlers/mendeley_handler/mendeley_tables.py +24 -29
- mindsdb/integrations/handlers/mendeley_handler/tests/test_mendeley_handler.py +19 -17
- mindsdb/integrations/handlers/merlion_handler/merlion_handler.py +5 -4
- mindsdb/integrations/handlers/minds_endpoint_handler/__init__.py +3 -3
- mindsdb/integrations/handlers/mlflow_handler/mlflow_handler.py +58 -36
- mindsdb/integrations/handlers/monetdb_handler/__about__.py +8 -8
- mindsdb/integrations/handlers/monetdb_handler/__init__.py +15 -5
- mindsdb/integrations/handlers/monetdb_handler/connection_args.py +17 -18
- mindsdb/integrations/handlers/monetdb_handler/monetdb_handler.py +40 -57
- mindsdb/integrations/handlers/monetdb_handler/tests/test_monetdb_handler.py +7 -8
- mindsdb/integrations/handlers/monetdb_handler/utils/monet_get_id.py +13 -14
- mindsdb/integrations/handlers/monkeylearn_handler/__about__.py +1 -1
- mindsdb/integrations/handlers/monkeylearn_handler/__init__.py +1 -1
- mindsdb/integrations/handlers/monkeylearn_handler/monkeylearn_handler.py +2 -5
- mindsdb/integrations/handlers/ms_one_drive_handler/ms_graph_api_one_drive_client.py +1 -0
- mindsdb/integrations/handlers/ms_one_drive_handler/ms_one_drive_handler.py +1 -1
- mindsdb/integrations/handlers/ms_teams_handler/ms_graph_api_teams_client.py +23 -23
- mindsdb/integrations/handlers/ms_teams_handler/ms_teams_handler.py +3 -3
- mindsdb/integrations/handlers/ms_teams_handler/ms_teams_tables.py +10 -5
- mindsdb/integrations/handlers/mssql_handler/mssql_handler.py +73 -8
- mindsdb/integrations/handlers/mysql_handler/__about__.py +8 -8
- mindsdb/integrations/handlers/mysql_handler/__init__.py +15 -5
- mindsdb/integrations/handlers/mysql_handler/connection_args.py +43 -47
- mindsdb/integrations/handlers/mysql_handler/mysql_handler.py +101 -34
- mindsdb/integrations/handlers/mysql_handler/settings.py +15 -13
- mindsdb/integrations/handlers/neuralforecast_handler/neuralforecast_handler.py +1 -1
- mindsdb/integrations/handlers/newsapi_handler/newsapi_handler.py +1 -1
- mindsdb/integrations/handlers/newsapi_handler/tests/test_newsapi_handler.py +4 -4
- mindsdb/integrations/handlers/nuo_jdbc_handler/connection_args.py +2 -2
- mindsdb/integrations/handlers/nuo_jdbc_handler/nuo_jdbc_handler.py +28 -36
- mindsdb/integrations/handlers/nuo_jdbc_handler/tests/test_nuo_handler.py +5 -5
- mindsdb/integrations/handlers/oceanbase_handler/oceanbase_handler.py +0 -1
- mindsdb/integrations/handlers/oceanbase_handler/tests/test_oceanbase_handler.py +8 -10
- mindsdb/integrations/handlers/ollama_handler/ollama_handler.py +3 -3
- mindsdb/integrations/handlers/opengauss_handler/tests/test_opengauss_handler.py +1 -2
- mindsdb/integrations/handlers/openstreetmap_handler/__init__.py +7 -7
- mindsdb/integrations/handlers/oracle_handler/connection_args.py +6 -0
- mindsdb/integrations/handlers/oracle_handler/oracle_handler.py +77 -11
- mindsdb/integrations/handlers/orioledb_handler/tests/test_orioledb_handler.py +8 -10
- mindsdb/integrations/handlers/palm_handler/__about__.py +1 -1
- mindsdb/integrations/handlers/palm_handler/__init__.py +1 -1
- mindsdb/integrations/handlers/palm_handler/palm_handler.py +1 -3
- mindsdb/integrations/handlers/paypal_handler/paypal_handler.py +2 -2
- mindsdb/integrations/handlers/paypal_handler/paypal_tables.py +15 -14
- mindsdb/integrations/handlers/pgvector_handler/pgvector_handler.py +53 -10
- mindsdb/integrations/handlers/phoenix_handler/__init__.py +1 -1
- mindsdb/integrations/handlers/phoenix_handler/phoenix_handler.py +1 -0
- mindsdb/integrations/handlers/pinot_handler/__init__.py +1 -1
- mindsdb/integrations/handlers/pinot_handler/pinot_handler.py +3 -2
- mindsdb/integrations/handlers/plaid_handler/plaid_handler.py +13 -13
- mindsdb/integrations/handlers/plaid_handler/plaid_tables.py +10 -12
- mindsdb/integrations/handlers/plaid_handler/utils.py +4 -6
- mindsdb/integrations/handlers/planetscale_handler/planetscale_handler.py +1 -4
- mindsdb/integrations/handlers/portkey_handler/__init__.py +2 -2
- mindsdb/integrations/handlers/postgres_handler/postgres_handler.py +105 -24
- mindsdb/integrations/handlers/postgres_handler/tests/test_postgres_handler.py +11 -6
- mindsdb/integrations/handlers/questdb_handler/questdb_handler.py +1 -2
- mindsdb/integrations/handlers/questdb_handler/tests/test_questdb_handler.py +2 -3
- mindsdb/integrations/handlers/quickbooks_handler/quickbooks_handler.py +6 -8
- mindsdb/integrations/handlers/quickbooks_handler/quickbooks_table.py +10 -10
- mindsdb/integrations/handlers/rag_handler/ingest.py +2 -2
- mindsdb/integrations/handlers/rag_handler/rag_handler.py +1 -1
- mindsdb/integrations/handlers/rag_handler/settings.py +1 -1
- mindsdb/integrations/handlers/reddit_handler/reddit_handler.py +2 -7
- mindsdb/integrations/handlers/reddit_handler/reddit_tables.py +2 -3
- mindsdb/integrations/handlers/replicate_handler/replicate_handler.py +6 -6
- mindsdb/integrations/handlers/rocket_chat_handler/rocket_chat_handler.py +1 -2
- mindsdb/integrations/handlers/rocket_chat_handler/rocket_chat_tables.py +0 -3
- mindsdb/integrations/handlers/rockset_handler/connection_args.py +14 -14
- mindsdb/integrations/handlers/rockset_handler/tests/test_rockset_handler.py +1 -0
- mindsdb/integrations/handlers/scylla_handler/scylla_handler.py +6 -5
- mindsdb/integrations/handlers/sendinblue_handler/sendinblue_handler.py +2 -1
- mindsdb/integrations/handlers/sendinblue_handler/sendinblue_tables.py +16 -16
- mindsdb/integrations/handlers/sentence_transformers_handler/__init__.py +1 -1
- mindsdb/integrations/handlers/sheets_handler/connection_args.py +1 -1
- mindsdb/integrations/handlers/shopify_handler/shopify_handler.py +7 -6
- mindsdb/integrations/handlers/shopify_handler/shopify_tables.py +38 -41
- mindsdb/integrations/handlers/singlestore_handler/__about__.py +1 -1
- mindsdb/integrations/handlers/singlestore_handler/__init__.py +0 -1
- mindsdb/integrations/handlers/singlestore_handler/singlestore_handler.py +1 -0
- mindsdb/integrations/handlers/singlestore_handler/tests/test_singlestore_handler.py +3 -3
- mindsdb/integrations/handlers/slack_handler/__init__.py +3 -3
- mindsdb/integrations/handlers/snowflake_handler/snowflake_handler.py +100 -6
- mindsdb/integrations/handlers/solr_handler/connection_args.py +7 -7
- mindsdb/integrations/handlers/solr_handler/solr_handler.py +2 -1
- mindsdb/integrations/handlers/solr_handler/tests/test_solr_handler.py +2 -1
- mindsdb/integrations/handlers/sqlany_handler/sqlany_handler.py +3 -2
- mindsdb/integrations/handlers/sqlite_handler/sqlite_handler.py +1 -0
- mindsdb/integrations/handlers/sqreamdb_handler/connection_args.py +1 -1
- mindsdb/integrations/handlers/sqreamdb_handler/sqreamdb_handler.py +15 -20
- mindsdb/integrations/handlers/sqreamdb_handler/tests/test_sqreamdb_handler.py +4 -4
- mindsdb/integrations/handlers/stabilityai_handler/__init__.py +1 -1
- mindsdb/integrations/handlers/starrocks_handler/starrocks_handler.py +0 -1
- mindsdb/integrations/handlers/starrocks_handler/tests/test_starrocks_handler.py +8 -10
- mindsdb/integrations/handlers/statsforecast_handler/statsforecast_handler.py +2 -2
- mindsdb/integrations/handlers/strava_handler/strava_handler.py +4 -8
- mindsdb/integrations/handlers/strava_handler/strava_tables.py +22 -30
- mindsdb/integrations/handlers/stripe_handler/stripe_handler.py +3 -2
- mindsdb/integrations/handlers/stripe_handler/stripe_tables.py +11 -27
- mindsdb/integrations/handlers/supabase_handler/tests/test_supabase_handler.py +1 -1
- mindsdb/integrations/handlers/surrealdb_handler/surrealdb_handler.py +4 -4
- mindsdb/integrations/handlers/tdengine_handler/tdengine_handler.py +25 -27
- mindsdb/integrations/handlers/tdengine_handler/tests/test_tdengine_handler.py +8 -8
- mindsdb/integrations/handlers/tidb_handler/tests/test_tidb_handler.py +1 -2
- mindsdb/integrations/handlers/timegpt_handler/timegpt_handler.py +5 -5
- mindsdb/integrations/handlers/tpot_handler/tpot_handler.py +21 -26
- mindsdb/integrations/handlers/trino_handler/trino_handler.py +14 -14
- mindsdb/integrations/handlers/twitter_handler/twitter_handler.py +2 -4
- mindsdb/integrations/handlers/unify_handler/tests/test_unify_handler.py +7 -8
- mindsdb/integrations/handlers/unify_handler/unify_handler.py +9 -9
- mindsdb/integrations/handlers/vertex_handler/vertex_client.py +1 -1
- mindsdb/integrations/handlers/vertica_handler/tests/test_vertica_handler.py +11 -11
- mindsdb/integrations/handlers/vertica_handler/vertica_handler.py +11 -14
- mindsdb/integrations/handlers/vitess_handler/tests/test_vitess_handler.py +9 -11
- mindsdb/integrations/handlers/vitess_handler/vitess_handler.py +0 -1
- mindsdb/integrations/handlers/web_handler/web_handler.py +1 -0
- mindsdb/integrations/handlers/whatsapp_handler/__init__.py +3 -3
- mindsdb/integrations/handlers/writer_handler/evaluate.py +1 -1
- mindsdb/integrations/handlers/writer_handler/settings.py +0 -1
- mindsdb/integrations/handlers/writer_handler/writer_handler.py +1 -0
- mindsdb/integrations/handlers/youtube_handler/youtube_handler.py +5 -5
- mindsdb/integrations/handlers/youtube_handler/youtube_tables.py +26 -27
- mindsdb/integrations/handlers/yugabyte_handler/tests/test_yugabyte_handler.py +3 -3
- mindsdb/integrations/handlers/yugabyte_handler/yugabyte_handler.py +0 -6
- mindsdb/integrations/libs/llm/config.py +13 -0
- mindsdb/integrations/libs/llm/utils.py +37 -65
- mindsdb/integrations/libs/response.py +67 -52
- mindsdb/integrations/libs/vectordatabase_handler.py +6 -0
- mindsdb/integrations/utilities/handler_utils.py +15 -3
- mindsdb/integrations/utilities/handlers/api_utilities/__init__.py +0 -1
- mindsdb/integrations/utilities/handlers/auth_utilities/__init__.py +0 -2
- mindsdb/integrations/utilities/rag/rerankers/base_reranker.py +230 -227
- mindsdb/integrations/utilities/utils.py +3 -3
- mindsdb/interfaces/agents/agents_controller.py +164 -1
- mindsdb/interfaces/agents/constants.py +32 -13
- mindsdb/interfaces/agents/langchain_agent.py +106 -95
- mindsdb/interfaces/agents/mindsdb_database_agent.py +101 -2
- mindsdb/interfaces/knowledge_base/controller.py +250 -216
- mindsdb/interfaces/knowledge_base/preprocessing/document_preprocessor.py +13 -10
- mindsdb/interfaces/knowledge_base/preprocessing/json_chunker.py +434 -0
- mindsdb/interfaces/knowledge_base/preprocessing/models.py +54 -0
- mindsdb/interfaces/query_context/context_controller.py +66 -10
- mindsdb/interfaces/skills/custom/text2sql/mindsdb_kb_tools.py +190 -0
- mindsdb/interfaces/skills/custom/text2sql/mindsdb_sql_toolkit.py +92 -0
- mindsdb/interfaces/skills/skill_tool.py +202 -57
- mindsdb/interfaces/skills/sql_agent.py +205 -17
- mindsdb/interfaces/storage/fs.py +1 -0
- mindsdb/interfaces/variables/__init__.py +0 -0
- mindsdb/interfaces/variables/variables_controller.py +97 -0
- mindsdb/migrations/env.py +5 -7
- mindsdb/migrations/migrate.py +47 -7
- mindsdb/migrations/versions/2025-05-21_9f150e4f9a05_checkpoint_1.py +360 -0
- mindsdb/utilities/config.py +287 -216
- mindsdb/utilities/starters.py +13 -0
- {mindsdb-25.5.3.0.dist-info → mindsdb-25.5.4.1.dist-info}/METADATA +646 -698
- {mindsdb-25.5.3.0.dist-info → mindsdb-25.5.4.1.dist-info}/RECORD +312 -295
- {mindsdb-25.5.3.0.dist-info → mindsdb-25.5.4.1.dist-info}/WHEEL +1 -1
- mindsdb/integrations/handlers/monkeylearn_handler/requirements.txt +0 -1
- {mindsdb-25.5.3.0.dist-info → mindsdb-25.5.4.1.dist-info}/licenses/LICENSE +0 -0
- {mindsdb-25.5.3.0.dist-info → mindsdb-25.5.4.1.dist-info}/top_level.txt +0 -0
|
@@ -20,121 +20,109 @@ from mindsdb.integrations.libs.response import HandlerStatusResponse
|
|
|
20
20
|
logger = log.getLogger(__name__)
|
|
21
21
|
|
|
22
22
|
|
|
23
|
-
@ns_conf.route(
|
|
24
|
-
@ns_conf.param(
|
|
23
|
+
@ns_conf.route("/")
|
|
24
|
+
@ns_conf.param("name", "Get config")
|
|
25
25
|
class GetConfig(Resource):
|
|
26
|
-
@ns_conf.doc(
|
|
27
|
-
@api_endpoint_metrics(
|
|
26
|
+
@ns_conf.doc("get_config")
|
|
27
|
+
@api_endpoint_metrics("GET", "/config")
|
|
28
28
|
def get(self):
|
|
29
29
|
config = Config()
|
|
30
|
-
resp = {
|
|
31
|
-
|
|
32
|
-
'http_auth_enabled': config['auth']['http_auth_enabled']
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
for key in ['default_llm', 'default_embedding_model']:
|
|
30
|
+
resp = {"auth": {"http_auth_enabled": config["auth"]["http_auth_enabled"]}}
|
|
31
|
+
for key in ["default_llm", "default_embedding_model", "default_reranking_model"]:
|
|
36
32
|
value = config.get(key)
|
|
37
33
|
if value is not None:
|
|
38
34
|
resp[key] = value
|
|
39
35
|
return resp
|
|
40
36
|
|
|
41
|
-
@ns_conf.doc(
|
|
42
|
-
@api_endpoint_metrics(
|
|
37
|
+
@ns_conf.doc("put_config")
|
|
38
|
+
@api_endpoint_metrics("PUT", "/config")
|
|
43
39
|
def put(self):
|
|
44
40
|
data = request.json
|
|
45
41
|
|
|
46
|
-
allowed_arguments = {
|
|
42
|
+
allowed_arguments = {"auth", "default_llm", "default_embedding_model", "default_reranking_model"}
|
|
47
43
|
unknown_arguments = list(set(data.keys()) - allowed_arguments)
|
|
48
44
|
if len(unknown_arguments) > 0:
|
|
49
|
-
return http_error(
|
|
50
|
-
HTTPStatus.BAD_REQUEST, 'Wrong arguments',
|
|
51
|
-
f'Unknown argumens: {unknown_arguments}'
|
|
52
|
-
)
|
|
45
|
+
return http_error(HTTPStatus.BAD_REQUEST, "Wrong arguments", f"Unknown argumens: {unknown_arguments}")
|
|
53
46
|
|
|
54
|
-
nested_keys_to_validate = {
|
|
47
|
+
nested_keys_to_validate = {"auth"}
|
|
55
48
|
for key in data.keys():
|
|
56
49
|
if key in nested_keys_to_validate:
|
|
57
|
-
unknown_arguments = list(
|
|
58
|
-
set(data[key].keys()) - set(Config()[key].keys())
|
|
59
|
-
)
|
|
50
|
+
unknown_arguments = list(set(data[key].keys()) - set(Config()[key].keys()))
|
|
60
51
|
if len(unknown_arguments) > 0:
|
|
61
52
|
return http_error(
|
|
62
|
-
HTTPStatus.BAD_REQUEST,
|
|
63
|
-
f'Unknown argumens: {unknown_arguments}'
|
|
53
|
+
HTTPStatus.BAD_REQUEST, "Wrong arguments", f"Unknown argumens: {unknown_arguments}"
|
|
64
54
|
)
|
|
65
55
|
|
|
66
56
|
Config().update(data)
|
|
67
57
|
|
|
68
|
-
return
|
|
58
|
+
return "", 200
|
|
69
59
|
|
|
70
60
|
|
|
71
|
-
@ns_conf.route(
|
|
72
|
-
@ns_conf.param(
|
|
61
|
+
@ns_conf.route("/integrations")
|
|
62
|
+
@ns_conf.param("name", "List all database integration")
|
|
73
63
|
class ListIntegration(Resource):
|
|
74
|
-
@api_endpoint_metrics(
|
|
64
|
+
@api_endpoint_metrics("GET", "/config/integrations")
|
|
75
65
|
def get(self):
|
|
76
|
-
return {
|
|
77
|
-
'integrations': [k for k in ca.integration_controller.get_all(show_secrets=False)]
|
|
78
|
-
}
|
|
66
|
+
return {"integrations": [k for k in ca.integration_controller.get_all(show_secrets=False)]}
|
|
79
67
|
|
|
80
68
|
|
|
81
|
-
@ns_conf.route(
|
|
82
|
-
@ns_conf.param(
|
|
69
|
+
@ns_conf.route("/all_integrations")
|
|
70
|
+
@ns_conf.param("name", "List all database integration")
|
|
83
71
|
class AllIntegration(Resource):
|
|
84
|
-
@ns_conf.doc(
|
|
85
|
-
@api_endpoint_metrics(
|
|
72
|
+
@ns_conf.doc("get_all_integrations")
|
|
73
|
+
@api_endpoint_metrics("GET", "/config/all_integrations")
|
|
86
74
|
def get(self):
|
|
87
75
|
integrations = ca.integration_controller.get_all(show_secrets=False)
|
|
88
76
|
return integrations
|
|
89
77
|
|
|
90
78
|
|
|
91
|
-
@ns_conf.route(
|
|
92
|
-
@ns_conf.param(
|
|
79
|
+
@ns_conf.route("/integrations/<name>")
|
|
80
|
+
@ns_conf.param("name", "Database integration")
|
|
93
81
|
class Integration(Resource):
|
|
94
|
-
@ns_conf.doc(
|
|
95
|
-
@api_endpoint_metrics(
|
|
82
|
+
@ns_conf.doc("get_integration")
|
|
83
|
+
@api_endpoint_metrics("GET", "/config/integrations/integration")
|
|
96
84
|
def get(self, name):
|
|
97
85
|
integration = ca.integration_controller.get(name, show_secrets=False)
|
|
98
86
|
if integration is None:
|
|
99
|
-
return http_error(HTTPStatus.NOT_FOUND,
|
|
87
|
+
return http_error(HTTPStatus.NOT_FOUND, "Not found", f"Can't find integration: {name}")
|
|
100
88
|
integration = copy.deepcopy(integration)
|
|
101
89
|
return integration
|
|
102
90
|
|
|
103
|
-
@ns_conf.doc(
|
|
104
|
-
@api_endpoint_metrics(
|
|
91
|
+
@ns_conf.doc("put_integration")
|
|
92
|
+
@api_endpoint_metrics("PUT", "/config/integrations/integration")
|
|
105
93
|
def put(self, name):
|
|
106
94
|
params = {}
|
|
107
95
|
if request.is_json:
|
|
108
|
-
params.update((request.json or {}).get(
|
|
96
|
+
params.update((request.json or {}).get("params", {}))
|
|
109
97
|
else:
|
|
110
98
|
params.update(request.form or {})
|
|
111
99
|
|
|
112
100
|
if len(params) == 0:
|
|
113
|
-
return http_error(HTTPStatus.BAD_REQUEST,
|
|
101
|
+
return http_error(HTTPStatus.BAD_REQUEST, "Wrong argument", "type of 'params' must be dict")
|
|
114
102
|
|
|
115
103
|
files = request.files
|
|
116
104
|
temp_dir = None
|
|
117
105
|
if files is not None and len(files) > 0:
|
|
118
|
-
temp_dir = tempfile.mkdtemp(prefix=
|
|
106
|
+
temp_dir = tempfile.mkdtemp(prefix="integration_files_")
|
|
119
107
|
for key, file in files.items():
|
|
120
108
|
temp_dir_path = Path(temp_dir)
|
|
121
109
|
file_name = Path(file.filename)
|
|
122
110
|
file_path = temp_dir_path.joinpath(file_name).resolve()
|
|
123
111
|
if temp_dir_path not in file_path.parents:
|
|
124
|
-
raise Exception(f
|
|
112
|
+
raise Exception(f"Can not save file at path: {file_path}")
|
|
125
113
|
file.save(file_path)
|
|
126
114
|
params[key] = str(file_path)
|
|
127
115
|
|
|
128
|
-
is_test = params.get(
|
|
116
|
+
is_test = params.get("test", False)
|
|
129
117
|
# TODO: Move this to new Endpoint
|
|
130
118
|
|
|
131
119
|
config = Config()
|
|
132
|
-
secret_key = config.get(
|
|
120
|
+
secret_key = config.get("secret_key", "dummy-key")
|
|
133
121
|
|
|
134
122
|
if is_test:
|
|
135
|
-
del params[
|
|
136
|
-
handler_type = params.pop(
|
|
137
|
-
params.pop(
|
|
123
|
+
del params["test"]
|
|
124
|
+
handler_type = params.pop("type", None)
|
|
125
|
+
params.pop("publish", None)
|
|
138
126
|
try:
|
|
139
127
|
handler = ca.integration_controller.create_tmp_handler(name, handler_type, params)
|
|
140
128
|
status = handler.check_connection()
|
|
@@ -145,33 +133,32 @@ class Integration(Resource):
|
|
|
145
133
|
|
|
146
134
|
resp = status.to_json()
|
|
147
135
|
|
|
148
|
-
if status.success and
|
|
149
|
-
if hasattr(handler,
|
|
136
|
+
if status.success and "code" in params:
|
|
137
|
+
if hasattr(handler, "handler_storage"):
|
|
150
138
|
# attach storage if exists
|
|
151
139
|
export = handler.handler_storage.export_files()
|
|
152
140
|
if export:
|
|
153
141
|
# encrypt with flask secret key
|
|
154
142
|
encrypted = encrypt(export, secret_key)
|
|
155
|
-
resp[
|
|
143
|
+
resp["storage"] = encrypted.decode()
|
|
156
144
|
|
|
157
145
|
return resp, 200
|
|
158
146
|
|
|
159
147
|
config = Config()
|
|
160
|
-
secret_key = config.get(
|
|
148
|
+
secret_key = config.get("secret_key", "dummy-key")
|
|
161
149
|
|
|
162
150
|
integration = ca.integration_controller.get(name, show_secrets=False)
|
|
163
151
|
if integration is not None:
|
|
164
152
|
return http_error(
|
|
165
|
-
HTTPStatus.BAD_REQUEST,
|
|
166
|
-
f"Integration with name '{name}' already exists"
|
|
153
|
+
HTTPStatus.BAD_REQUEST, "Wrong argument", f"Integration with name '{name}' already exists"
|
|
167
154
|
)
|
|
168
155
|
|
|
169
156
|
try:
|
|
170
|
-
engine = params[
|
|
157
|
+
engine = params["type"]
|
|
171
158
|
if engine is not None:
|
|
172
|
-
del params[
|
|
173
|
-
params.pop(
|
|
174
|
-
storage = params.pop(
|
|
159
|
+
del params["type"]
|
|
160
|
+
params.pop("publish", False)
|
|
161
|
+
storage = params.pop("storage", None)
|
|
175
162
|
ca.integration_controller.add(name, engine, params)
|
|
176
163
|
|
|
177
164
|
# copy storage
|
|
@@ -185,62 +172,50 @@ class Integration(Resource):
|
|
|
185
172
|
logger.error(str(e))
|
|
186
173
|
if temp_dir is not None:
|
|
187
174
|
shutil.rmtree(temp_dir)
|
|
188
|
-
return http_error(
|
|
189
|
-
HTTPStatus.INTERNAL_SERVER_ERROR, 'Error',
|
|
190
|
-
f'Error during config update: {str(e)}'
|
|
191
|
-
)
|
|
175
|
+
return http_error(HTTPStatus.INTERNAL_SERVER_ERROR, "Error", f"Error during config update: {str(e)}")
|
|
192
176
|
|
|
193
177
|
if temp_dir is not None:
|
|
194
178
|
shutil.rmtree(temp_dir)
|
|
195
179
|
return {}, 200
|
|
196
180
|
|
|
197
|
-
@ns_conf.doc(
|
|
198
|
-
@api_endpoint_metrics(
|
|
181
|
+
@ns_conf.doc("delete_integration")
|
|
182
|
+
@api_endpoint_metrics("DELETE", "/config/integrations/integration")
|
|
199
183
|
def delete(self, name):
|
|
200
184
|
integration = ca.integration_controller.get(name)
|
|
201
185
|
if integration is None:
|
|
202
186
|
return http_error(
|
|
203
|
-
HTTPStatus.BAD_REQUEST,
|
|
204
|
-
f"Nothing to delete. '{name}' not exists."
|
|
187
|
+
HTTPStatus.BAD_REQUEST, "Integration does not exists", f"Nothing to delete. '{name}' not exists."
|
|
205
188
|
)
|
|
206
189
|
try:
|
|
207
190
|
ca.integration_controller.delete(name)
|
|
208
191
|
except Exception as e:
|
|
209
192
|
logger.error(str(e))
|
|
210
|
-
return http_error(
|
|
211
|
-
HTTPStatus.INTERNAL_SERVER_ERROR, 'Error',
|
|
212
|
-
f"Error during integration delete: {str(e)}"
|
|
213
|
-
)
|
|
193
|
+
return http_error(HTTPStatus.INTERNAL_SERVER_ERROR, "Error", f"Error during integration delete: {str(e)}")
|
|
214
194
|
return "", 200
|
|
215
195
|
|
|
216
|
-
@ns_conf.doc(
|
|
217
|
-
@api_endpoint_metrics(
|
|
196
|
+
@ns_conf.doc("modify_integration")
|
|
197
|
+
@api_endpoint_metrics("POST", "/config/integrations/integration")
|
|
218
198
|
def post(self, name):
|
|
219
199
|
params = {}
|
|
220
|
-
params.update((request.json or {}).get(
|
|
200
|
+
params.update((request.json or {}).get("params", {}))
|
|
221
201
|
params.update(request.form or {})
|
|
222
202
|
|
|
223
203
|
if not isinstance(params, dict):
|
|
224
|
-
return http_error(
|
|
225
|
-
HTTPStatus.BAD_REQUEST, 'Wrong argument',
|
|
226
|
-
"type of 'params' must be dict"
|
|
227
|
-
)
|
|
204
|
+
return http_error(HTTPStatus.BAD_REQUEST, "Wrong argument", "type of 'params' must be dict")
|
|
228
205
|
integration = ca.integration_controller.get(name)
|
|
229
206
|
if integration is None:
|
|
230
207
|
return http_error(
|
|
231
|
-
HTTPStatus.BAD_REQUEST,
|
|
232
|
-
f"Nothin to modify. '{name}' not exists."
|
|
208
|
+
HTTPStatus.BAD_REQUEST, "Integration does not exists", f"Nothin to modify. '{name}' not exists."
|
|
233
209
|
)
|
|
234
210
|
try:
|
|
235
|
-
if
|
|
236
|
-
params[
|
|
237
|
-
del params[
|
|
211
|
+
if "enabled" in params:
|
|
212
|
+
params["publish"] = params["enabled"]
|
|
213
|
+
del params["enabled"]
|
|
238
214
|
ca.integration_controller.modify(name, params)
|
|
239
215
|
|
|
240
216
|
except Exception as e:
|
|
241
217
|
logger.error(str(e))
|
|
242
218
|
return http_error(
|
|
243
|
-
HTTPStatus.INTERNAL_SERVER_ERROR,
|
|
244
|
-
f"Error during integration modification: {str(e)}"
|
|
219
|
+
HTTPStatus.INTERNAL_SERVER_ERROR, "Error", f"Error during integration modification: {str(e)}"
|
|
245
220
|
)
|
|
246
221
|
return "", 200
|
|
@@ -84,8 +84,14 @@ class File(Resource):
|
|
|
84
84
|
parser.finalize()
|
|
85
85
|
parser.close()
|
|
86
86
|
|
|
87
|
-
if file_object is not None
|
|
88
|
-
file_object.
|
|
87
|
+
if file_object is not None:
|
|
88
|
+
if not file_object.closed:
|
|
89
|
+
try:
|
|
90
|
+
file_object.flush()
|
|
91
|
+
except (AttributeError, ValueError, OSError):
|
|
92
|
+
logger.debug("Failed to flush file_object before closing.", exc_info=True)
|
|
93
|
+
file_object.close()
|
|
94
|
+
file_object = None
|
|
89
95
|
else:
|
|
90
96
|
data = request.json
|
|
91
97
|
|
|
@@ -8,6 +8,7 @@ import mindsdb.utilities.hooks as hooks
|
|
|
8
8
|
import mindsdb.utilities.profiler as profiler
|
|
9
9
|
from mindsdb.api.http.utils import http_error
|
|
10
10
|
from mindsdb.api.http.namespaces.configs.sql import ns_conf
|
|
11
|
+
from mindsdb.api.mysql.mysql_proxy.mysql_proxy import SQLAnswer
|
|
11
12
|
from mindsdb.api.mysql.mysql_proxy.classes.fake_mysql_proxy import FakeMysqlProxy
|
|
12
13
|
from mindsdb.api.executor.data_types.response_type import (
|
|
13
14
|
RESPONSE_TYPE as SQL_RESPONSE_TYPE,
|
|
@@ -56,23 +57,8 @@ class Query(Resource):
|
|
|
56
57
|
mysql_proxy = FakeMysqlProxy()
|
|
57
58
|
mysql_proxy.set_context(context)
|
|
58
59
|
try:
|
|
59
|
-
result = mysql_proxy.process_query(query)
|
|
60
|
-
|
|
61
|
-
if result.type == SQL_RESPONSE_TYPE.OK:
|
|
62
|
-
query_response = {
|
|
63
|
-
"type": SQL_RESPONSE_TYPE.OK,
|
|
64
|
-
"affected_rows": result.affected_rows
|
|
65
|
-
}
|
|
66
|
-
elif result.type == SQL_RESPONSE_TYPE.TABLE:
|
|
67
|
-
data = result.data.to_lists(json_types=True)
|
|
68
|
-
query_response = {
|
|
69
|
-
"type": SQL_RESPONSE_TYPE.TABLE,
|
|
70
|
-
"data": data,
|
|
71
|
-
"column_names": [
|
|
72
|
-
x["alias"] or x["name"] if "alias" in x else x["name"]
|
|
73
|
-
for x in result.columns
|
|
74
|
-
],
|
|
75
|
-
}
|
|
60
|
+
result: SQLAnswer = mysql_proxy.process_query(query)
|
|
61
|
+
query_response: dict = result.dump_http_response()
|
|
76
62
|
except ExecutorException as e:
|
|
77
63
|
# classified error
|
|
78
64
|
error_type = "expected"
|
|
@@ -134,7 +120,7 @@ class ListDatabases(Resource):
|
|
|
134
120
|
listing_query = "SHOW DATABASES"
|
|
135
121
|
mysql_proxy = FakeMysqlProxy()
|
|
136
122
|
try:
|
|
137
|
-
result = mysql_proxy.process_query(listing_query)
|
|
123
|
+
result: SQLAnswer = mysql_proxy.process_query(listing_query)
|
|
138
124
|
|
|
139
125
|
# iterate over result.data and perform a query on each item to get the name of the tables
|
|
140
126
|
if result.type == SQL_RESPONSE_TYPE.ERROR:
|
|
@@ -147,15 +133,15 @@ class ListDatabases(Resource):
|
|
|
147
133
|
listing_query_response = {"type": "ok"}
|
|
148
134
|
elif result.type == SQL_RESPONSE_TYPE.TABLE:
|
|
149
135
|
listing_query_response = {
|
|
150
|
-
"data": [
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
]
|
|
136
|
+
"data": [{
|
|
137
|
+
"name": db_row[0],
|
|
138
|
+
"tables": [
|
|
139
|
+
table_row[0]
|
|
140
|
+
for table_row in mysql_proxy.process_query(
|
|
141
|
+
"SHOW TABLES FROM `{}`".format(db_row[0])
|
|
142
|
+
).result_set.to_lists()
|
|
143
|
+
]
|
|
144
|
+
} for db_row in result.result_set.to_lists()]
|
|
159
145
|
}
|
|
160
146
|
except Exception as e:
|
|
161
147
|
listing_query_response = {
|
mindsdb/api/mcp/start.py
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
|
+
import os
|
|
1
2
|
from contextlib import asynccontextmanager
|
|
2
3
|
from collections.abc import AsyncIterator
|
|
3
4
|
from typing import Optional, Dict, Any
|
|
4
5
|
from dataclasses import dataclass
|
|
5
6
|
|
|
7
|
+
import uvicorn
|
|
8
|
+
import anyio
|
|
6
9
|
from mcp.server.fastmcp import FastMCP
|
|
10
|
+
from starlette.middleware.base import BaseHTTPMiddleware
|
|
11
|
+
from starlette.requests import Request
|
|
12
|
+
from starlette.responses import Response
|
|
13
|
+
|
|
7
14
|
from mindsdb.api.mysql.mysql_proxy.classes.fake_mysql_proxy import FakeMysqlProxy
|
|
8
15
|
from mindsdb.api.executor.data_types.response_type import RESPONSE_TYPE as SQL_RESPONSE_TYPE
|
|
9
16
|
from mindsdb.utilities import log
|
|
@@ -70,10 +77,10 @@ def query(query: str, context: Optional[Dict] = None) -> Dict[str, Any]:
|
|
|
70
77
|
if result.type == SQL_RESPONSE_TYPE.TABLE:
|
|
71
78
|
return {
|
|
72
79
|
"type": SQL_RESPONSE_TYPE.TABLE,
|
|
73
|
-
"data": result.
|
|
80
|
+
"data": result.result_set.to_lists(json_types=True),
|
|
74
81
|
"column_names": [
|
|
75
|
-
|
|
76
|
-
for
|
|
82
|
+
column.alias or column.name
|
|
83
|
+
for column in result.result_set.columns
|
|
77
84
|
],
|
|
78
85
|
}
|
|
79
86
|
else:
|
|
@@ -116,7 +123,7 @@ def list_databases() -> Dict[str, Any]:
|
|
|
116
123
|
return {"type": "ok"}
|
|
117
124
|
|
|
118
125
|
elif result.type == SQL_RESPONSE_TYPE.TABLE:
|
|
119
|
-
data = result.
|
|
126
|
+
data = result.result_set.to_lists(json_types=True)
|
|
120
127
|
return data
|
|
121
128
|
|
|
122
129
|
except Exception as e:
|
|
@@ -127,6 +134,36 @@ def list_databases() -> Dict[str, Any]:
|
|
|
127
134
|
}
|
|
128
135
|
|
|
129
136
|
|
|
137
|
+
class CustomAuthMiddleware(BaseHTTPMiddleware):
|
|
138
|
+
"""Custom middleware to handle authentication basing on header 'Authorization'
|
|
139
|
+
"""
|
|
140
|
+
async def dispatch(self, request: Request, call_next):
|
|
141
|
+
mcp_access_token = os.environ.get('MINDSDB_MCP_ACCESS_TOKEN')
|
|
142
|
+
if mcp_access_token is not None:
|
|
143
|
+
auth_token = request.headers.get('Authorization', '').partition('Bearer ')[-1]
|
|
144
|
+
if mcp_access_token != auth_token:
|
|
145
|
+
return Response(status_code=401, content="Unauthorized", media_type="text/plain")
|
|
146
|
+
|
|
147
|
+
response = await call_next(request)
|
|
148
|
+
|
|
149
|
+
return response
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
async def run_sse_async() -> None:
|
|
153
|
+
"""Run the server using SSE transport."""
|
|
154
|
+
starlette_app = mcp.sse_app()
|
|
155
|
+
starlette_app.add_middleware(CustomAuthMiddleware)
|
|
156
|
+
|
|
157
|
+
config = uvicorn.Config(
|
|
158
|
+
starlette_app,
|
|
159
|
+
host=mcp.settings.host,
|
|
160
|
+
port=mcp.settings.port,
|
|
161
|
+
log_level=mcp.settings.log_level.lower(),
|
|
162
|
+
)
|
|
163
|
+
server = uvicorn.Server(config)
|
|
164
|
+
await server.serve()
|
|
165
|
+
|
|
166
|
+
|
|
130
167
|
def start(*args, **kwargs):
|
|
131
168
|
"""Start the MCP server
|
|
132
169
|
Args:
|
|
@@ -142,7 +179,7 @@ def start(*args, **kwargs):
|
|
|
142
179
|
mcp.settings.port = port
|
|
143
180
|
|
|
144
181
|
try:
|
|
145
|
-
|
|
182
|
+
anyio.run(run_sse_async)
|
|
146
183
|
except Exception as e:
|
|
147
184
|
logger.error(f"Error starting MCP server: {str(e)}")
|
|
148
185
|
raise
|
|
@@ -30,16 +30,18 @@ class BinaryResultsetRowPacket(Packet):
|
|
|
30
30
|
columns = self._kwargs.get('columns', {})
|
|
31
31
|
|
|
32
32
|
self.value = [b'\x00']
|
|
33
|
-
|
|
33
|
+
|
|
34
|
+
# NOTE: according to mysql's doc offset=0 only for COM_STMT_EXECUTE, mariadb's doc does't mention that
|
|
35
|
+
# but in fact it looks like offset=2 everywhere
|
|
36
|
+
offset = 2
|
|
37
|
+
nulls_bitmap = bytearray((len(columns) + offset + 7) // 8)
|
|
34
38
|
for i, el in enumerate(data):
|
|
35
|
-
if
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
nulls[-1] = nulls[-1] + (1 << ((i - 6) % 8))
|
|
42
|
-
self.value.append(bytes(nulls))
|
|
39
|
+
if el is not None:
|
|
40
|
+
continue
|
|
41
|
+
byte_index = (i + offset) // 8
|
|
42
|
+
bit_index = (i + offset) % 8
|
|
43
|
+
nulls_bitmap[byte_index] |= (1 << bit_index)
|
|
44
|
+
self.value.append(bytes(nulls_bitmap))
|
|
43
45
|
|
|
44
46
|
for i, col in enumerate(columns):
|
|
45
47
|
# NOTE at this moment all types sends as strings, and it works
|
|
@@ -65,6 +67,12 @@ class BinaryResultsetRowPacket(Packet):
|
|
|
65
67
|
elif col_type == TYPES.MYSQL_TYPE_YEAR:
|
|
66
68
|
enc = '<h'
|
|
67
69
|
val = int(float(val))
|
|
70
|
+
elif col_type == TYPES.MYSQL_TYPE_SHORT:
|
|
71
|
+
enc = '<h'
|
|
72
|
+
val = int(val)
|
|
73
|
+
elif col_type == TYPES.MYSQL_TYPE_TINY:
|
|
74
|
+
enc = '<B'
|
|
75
|
+
val = int(val)
|
|
68
76
|
elif col_type == TYPES.MYSQL_TYPE_DATE:
|
|
69
77
|
env_val = self.encode_date(val)
|
|
70
78
|
elif col_type == TYPES.MYSQL_TYPE_TIMESTAMP:
|
|
@@ -72,9 +80,9 @@ class BinaryResultsetRowPacket(Packet):
|
|
|
72
80
|
elif col_type == TYPES.MYSQL_TYPE_DATETIME:
|
|
73
81
|
env_val = self.encode_date(val)
|
|
74
82
|
elif col_type == TYPES.MYSQL_TYPE_TIME:
|
|
75
|
-
|
|
83
|
+
env_val = self.encode_time(val)
|
|
76
84
|
elif col_type == TYPES.MYSQL_TYPE_NEWDECIMAL:
|
|
77
|
-
enc = ''
|
|
85
|
+
enc = 'string'
|
|
78
86
|
else:
|
|
79
87
|
enc = 'string'
|
|
80
88
|
|
|
@@ -90,21 +98,46 @@ class BinaryResultsetRowPacket(Packet):
|
|
|
90
98
|
env_val = struct.pack(enc, val)
|
|
91
99
|
self.value.append(env_val)
|
|
92
100
|
|
|
101
|
+
def encode_time(self, val: dt.time | str) -> bytes:
|
|
102
|
+
""" https://mariadb.com/kb/en/resultset-row/#time-binary-encoding
|
|
103
|
+
"""
|
|
104
|
+
if isinstance(val, str):
|
|
105
|
+
try:
|
|
106
|
+
val = dt.datetime.strptime(val, '%H:%M:%S').time()
|
|
107
|
+
except ValueError:
|
|
108
|
+
val = dt.datetime.strptime(val, '%H:%M:%S.%f').time()
|
|
109
|
+
if val == dt.time(0, 0, 0):
|
|
110
|
+
return struct.pack('<B', 0) # special case for 0 time
|
|
111
|
+
out = struct.pack('<B', 0) # positive time
|
|
112
|
+
out += struct.pack('<L', 0) # days
|
|
113
|
+
out += struct.pack('<B', val.hour)
|
|
114
|
+
out += struct.pack('<B', val.minute)
|
|
115
|
+
out += struct.pack('<B', val.second)
|
|
116
|
+
if val.microsecond > 0:
|
|
117
|
+
out += struct.pack('<L', val.microsecond)
|
|
118
|
+
len_bit = struct.pack('<B', 12)
|
|
119
|
+
else:
|
|
120
|
+
len_bit = struct.pack('<B', 8)
|
|
121
|
+
return len_bit + out
|
|
122
|
+
|
|
93
123
|
def encode_date(self, val):
|
|
94
124
|
# date_type = None
|
|
95
125
|
# date_value = None
|
|
96
126
|
|
|
97
127
|
if isinstance(val, str):
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
128
|
+
forms = [
|
|
129
|
+
'%Y-%m-%d', '%Y-%m-%d %H:%M:%S', '%Y-%m-%d %H:%M:%S.%f',
|
|
130
|
+
'%Y-%m-%dT%H:%M:%S', '%Y-%m-%dT%H:%M:%S.%f'
|
|
131
|
+
]
|
|
132
|
+
for f in forms:
|
|
102
133
|
try:
|
|
103
|
-
date_value = dt.datetime.strptime(val,
|
|
104
|
-
|
|
134
|
+
date_value = dt.datetime.strptime(val, f)
|
|
135
|
+
break
|
|
105
136
|
except ValueError:
|
|
106
|
-
date_value =
|
|
107
|
-
|
|
137
|
+
date_value = None
|
|
138
|
+
if date_value is None:
|
|
139
|
+
raise ValueError(f"Invalid date format: {val}")
|
|
140
|
+
date_type = 'datetime'
|
|
108
141
|
elif isinstance(val, pd.Timestamp):
|
|
109
142
|
date_value = val
|
|
110
143
|
date_type = 'datetime'
|
|
@@ -7,6 +7,7 @@ from mindsdb.api.executor.sql_query import SQLQuery
|
|
|
7
7
|
from mindsdb.api.executor.data_types.answer import ExecuteAnswer
|
|
8
8
|
from mindsdb.api.executor.command_executor import ExecuteCommands
|
|
9
9
|
from mindsdb.api.mysql.mysql_proxy.utilities import ErSqlSyntaxError
|
|
10
|
+
from mindsdb.api.mysql.mysql_proxy.libs.constants.mysql import MYSQL_DATA_TYPE
|
|
10
11
|
from mindsdb.utilities import log
|
|
11
12
|
|
|
12
13
|
logger = log.getLogger(__name__)
|
|
@@ -19,8 +20,8 @@ class Executor:
|
|
|
19
20
|
|
|
20
21
|
self.query = None
|
|
21
22
|
|
|
22
|
-
self.columns = []
|
|
23
|
-
self.params = []
|
|
23
|
+
self.columns: list[Column] = []
|
|
24
|
+
self.params: list[Column] = []
|
|
24
25
|
self.data = None
|
|
25
26
|
self.server_status = None
|
|
26
27
|
self.is_executed = False
|
|
@@ -56,14 +57,11 @@ class Executor:
|
|
|
56
57
|
|
|
57
58
|
sqlquery.prepare_query()
|
|
58
59
|
|
|
59
|
-
self.params = [
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
)
|
|
65
|
-
for p in params
|
|
66
|
-
]
|
|
60
|
+
self.params = [Column(
|
|
61
|
+
name=p.value,
|
|
62
|
+
alias=p.value,
|
|
63
|
+
type=MYSQL_DATA_TYPE.TEXT
|
|
64
|
+
) for p in params]
|
|
67
65
|
|
|
68
66
|
# TODO:
|
|
69
67
|
# select * from mindsdb.models doesn't invoke prepare_steps and columns_list is empty
|