@neverinfamous/postgres-mcp 1.0.1
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.
- package/LICENSE +21 -0
- package/README.md +515 -0
- package/dist/__tests__/mocks/adapter.d.ts +80 -0
- package/dist/__tests__/mocks/adapter.d.ts.map +1 -0
- package/dist/__tests__/mocks/adapter.js +225 -0
- package/dist/__tests__/mocks/adapter.js.map +1 -0
- package/dist/__tests__/mocks/index.d.ts +11 -0
- package/dist/__tests__/mocks/index.d.ts.map +1 -0
- package/dist/__tests__/mocks/index.js +11 -0
- package/dist/__tests__/mocks/index.js.map +1 -0
- package/dist/__tests__/mocks/pool.d.ts +43 -0
- package/dist/__tests__/mocks/pool.d.ts.map +1 -0
- package/dist/__tests__/mocks/pool.js +71 -0
- package/dist/__tests__/mocks/pool.js.map +1 -0
- package/dist/adapters/DatabaseAdapter.d.ts +139 -0
- package/dist/adapters/DatabaseAdapter.d.ts.map +1 -0
- package/dist/adapters/DatabaseAdapter.js +250 -0
- package/dist/adapters/DatabaseAdapter.js.map +1 -0
- package/dist/adapters/postgresql/PostgresAdapter.d.ts +119 -0
- package/dist/adapters/postgresql/PostgresAdapter.d.ts.map +1 -0
- package/dist/adapters/postgresql/PostgresAdapter.js +902 -0
- package/dist/adapters/postgresql/PostgresAdapter.js.map +1 -0
- package/dist/adapters/postgresql/index.d.ts +5 -0
- package/dist/adapters/postgresql/index.d.ts.map +1 -0
- package/dist/adapters/postgresql/index.js +5 -0
- package/dist/adapters/postgresql/index.js.map +1 -0
- package/dist/adapters/postgresql/prompts/backup.d.ts +8 -0
- package/dist/adapters/postgresql/prompts/backup.d.ts.map +1 -0
- package/dist/adapters/postgresql/prompts/backup.js +132 -0
- package/dist/adapters/postgresql/prompts/backup.js.map +1 -0
- package/dist/adapters/postgresql/prompts/citext.d.ts +8 -0
- package/dist/adapters/postgresql/prompts/citext.d.ts.map +1 -0
- package/dist/adapters/postgresql/prompts/citext.js +227 -0
- package/dist/adapters/postgresql/prompts/citext.js.map +1 -0
- package/dist/adapters/postgresql/prompts/extensionSetup.d.ts +8 -0
- package/dist/adapters/postgresql/prompts/extensionSetup.d.ts.map +1 -0
- package/dist/adapters/postgresql/prompts/extensionSetup.js +282 -0
- package/dist/adapters/postgresql/prompts/extensionSetup.js.map +1 -0
- package/dist/adapters/postgresql/prompts/health.d.ts +8 -0
- package/dist/adapters/postgresql/prompts/health.d.ts.map +1 -0
- package/dist/adapters/postgresql/prompts/health.js +118 -0
- package/dist/adapters/postgresql/prompts/health.js.map +1 -0
- package/dist/adapters/postgresql/prompts/index.d.ts +13 -0
- package/dist/adapters/postgresql/prompts/index.d.ts.map +1 -0
- package/dist/adapters/postgresql/prompts/index.js +308 -0
- package/dist/adapters/postgresql/prompts/index.js.map +1 -0
- package/dist/adapters/postgresql/prompts/indexTuning.d.ts +8 -0
- package/dist/adapters/postgresql/prompts/indexTuning.d.ts.map +1 -0
- package/dist/adapters/postgresql/prompts/indexTuning.js +130 -0
- package/dist/adapters/postgresql/prompts/indexTuning.js.map +1 -0
- package/dist/adapters/postgresql/prompts/kcache.d.ts +8 -0
- package/dist/adapters/postgresql/prompts/kcache.d.ts.map +1 -0
- package/dist/adapters/postgresql/prompts/kcache.js +227 -0
- package/dist/adapters/postgresql/prompts/kcache.js.map +1 -0
- package/dist/adapters/postgresql/prompts/ltree.d.ts +8 -0
- package/dist/adapters/postgresql/prompts/ltree.d.ts.map +1 -0
- package/dist/adapters/postgresql/prompts/ltree.js +286 -0
- package/dist/adapters/postgresql/prompts/ltree.js.map +1 -0
- package/dist/adapters/postgresql/prompts/partman.d.ts +8 -0
- package/dist/adapters/postgresql/prompts/partman.d.ts.map +1 -0
- package/dist/adapters/postgresql/prompts/partman.js +211 -0
- package/dist/adapters/postgresql/prompts/partman.js.map +1 -0
- package/dist/adapters/postgresql/prompts/pgcron.d.ts +8 -0
- package/dist/adapters/postgresql/prompts/pgcron.d.ts.map +1 -0
- package/dist/adapters/postgresql/prompts/pgcron.js +233 -0
- package/dist/adapters/postgresql/prompts/pgcron.js.map +1 -0
- package/dist/adapters/postgresql/prompts/pgcrypto.d.ts +8 -0
- package/dist/adapters/postgresql/prompts/pgcrypto.d.ts.map +1 -0
- package/dist/adapters/postgresql/prompts/pgcrypto.js +299 -0
- package/dist/adapters/postgresql/prompts/pgcrypto.js.map +1 -0
- package/dist/adapters/postgresql/prompts/pgvector.d.ts +8 -0
- package/dist/adapters/postgresql/prompts/pgvector.d.ts.map +1 -0
- package/dist/adapters/postgresql/prompts/pgvector.js +148 -0
- package/dist/adapters/postgresql/prompts/pgvector.js.map +1 -0
- package/dist/adapters/postgresql/prompts/postgis.d.ts +8 -0
- package/dist/adapters/postgresql/prompts/postgis.d.ts.map +1 -0
- package/dist/adapters/postgresql/prompts/postgis.js +200 -0
- package/dist/adapters/postgresql/prompts/postgis.js.map +1 -0
- package/dist/adapters/postgresql/resources/activity.d.ts +9 -0
- package/dist/adapters/postgresql/resources/activity.d.ts.map +1 -0
- package/dist/adapters/postgresql/resources/activity.js +118 -0
- package/dist/adapters/postgresql/resources/activity.js.map +1 -0
- package/dist/adapters/postgresql/resources/capabilities.d.ts +9 -0
- package/dist/adapters/postgresql/resources/capabilities.d.ts.map +1 -0
- package/dist/adapters/postgresql/resources/capabilities.js +182 -0
- package/dist/adapters/postgresql/resources/capabilities.js.map +1 -0
- package/dist/adapters/postgresql/resources/cron.d.ts +9 -0
- package/dist/adapters/postgresql/resources/cron.d.ts.map +1 -0
- package/dist/adapters/postgresql/resources/cron.js +156 -0
- package/dist/adapters/postgresql/resources/cron.js.map +1 -0
- package/dist/adapters/postgresql/resources/crypto.d.ts +9 -0
- package/dist/adapters/postgresql/resources/crypto.d.ts.map +1 -0
- package/dist/adapters/postgresql/resources/crypto.js +191 -0
- package/dist/adapters/postgresql/resources/crypto.js.map +1 -0
- package/dist/adapters/postgresql/resources/extensions.d.ts +9 -0
- package/dist/adapters/postgresql/resources/extensions.d.ts.map +1 -0
- package/dist/adapters/postgresql/resources/extensions.js +85 -0
- package/dist/adapters/postgresql/resources/extensions.js.map +1 -0
- package/dist/adapters/postgresql/resources/health.d.ts +9 -0
- package/dist/adapters/postgresql/resources/health.d.ts.map +1 -0
- package/dist/adapters/postgresql/resources/health.js +185 -0
- package/dist/adapters/postgresql/resources/health.js.map +1 -0
- package/dist/adapters/postgresql/resources/index.d.ts +40 -0
- package/dist/adapters/postgresql/resources/index.d.ts.map +1 -0
- package/dist/adapters/postgresql/resources/index.js +87 -0
- package/dist/adapters/postgresql/resources/index.js.map +1 -0
- package/dist/adapters/postgresql/resources/indexes.d.ts +9 -0
- package/dist/adapters/postgresql/resources/indexes.d.ts.map +1 -0
- package/dist/adapters/postgresql/resources/indexes.js +130 -0
- package/dist/adapters/postgresql/resources/indexes.js.map +1 -0
- package/dist/adapters/postgresql/resources/kcache.d.ts +9 -0
- package/dist/adapters/postgresql/resources/kcache.d.ts.map +1 -0
- package/dist/adapters/postgresql/resources/kcache.js +219 -0
- package/dist/adapters/postgresql/resources/kcache.js.map +1 -0
- package/dist/adapters/postgresql/resources/locks.d.ts +9 -0
- package/dist/adapters/postgresql/resources/locks.d.ts.map +1 -0
- package/dist/adapters/postgresql/resources/locks.js +89 -0
- package/dist/adapters/postgresql/resources/locks.js.map +1 -0
- package/dist/adapters/postgresql/resources/partman.d.ts +9 -0
- package/dist/adapters/postgresql/resources/partman.d.ts.map +1 -0
- package/dist/adapters/postgresql/resources/partman.js +149 -0
- package/dist/adapters/postgresql/resources/partman.js.map +1 -0
- package/dist/adapters/postgresql/resources/performance.d.ts +9 -0
- package/dist/adapters/postgresql/resources/performance.d.ts.map +1 -0
- package/dist/adapters/postgresql/resources/performance.js +170 -0
- package/dist/adapters/postgresql/resources/performance.js.map +1 -0
- package/dist/adapters/postgresql/resources/pool.d.ts +9 -0
- package/dist/adapters/postgresql/resources/pool.d.ts.map +1 -0
- package/dist/adapters/postgresql/resources/pool.js +93 -0
- package/dist/adapters/postgresql/resources/pool.js.map +1 -0
- package/dist/adapters/postgresql/resources/postgis.d.ts +9 -0
- package/dist/adapters/postgresql/resources/postgis.d.ts.map +1 -0
- package/dist/adapters/postgresql/resources/postgis.js +232 -0
- package/dist/adapters/postgresql/resources/postgis.js.map +1 -0
- package/dist/adapters/postgresql/resources/replication.d.ts +9 -0
- package/dist/adapters/postgresql/resources/replication.d.ts.map +1 -0
- package/dist/adapters/postgresql/resources/replication.js +126 -0
- package/dist/adapters/postgresql/resources/replication.js.map +1 -0
- package/dist/adapters/postgresql/resources/schema.d.ts +10 -0
- package/dist/adapters/postgresql/resources/schema.d.ts.map +1 -0
- package/dist/adapters/postgresql/resources/schema.js +80 -0
- package/dist/adapters/postgresql/resources/schema.js.map +1 -0
- package/dist/adapters/postgresql/resources/settings.d.ts +9 -0
- package/dist/adapters/postgresql/resources/settings.d.ts.map +1 -0
- package/dist/adapters/postgresql/resources/settings.js +184 -0
- package/dist/adapters/postgresql/resources/settings.js.map +1 -0
- package/dist/adapters/postgresql/resources/stats.d.ts +10 -0
- package/dist/adapters/postgresql/resources/stats.d.ts.map +1 -0
- package/dist/adapters/postgresql/resources/stats.js +124 -0
- package/dist/adapters/postgresql/resources/stats.js.map +1 -0
- package/dist/adapters/postgresql/resources/tables.d.ts +9 -0
- package/dist/adapters/postgresql/resources/tables.d.ts.map +1 -0
- package/dist/adapters/postgresql/resources/tables.js +20 -0
- package/dist/adapters/postgresql/resources/tables.js.map +1 -0
- package/dist/adapters/postgresql/resources/vacuum.d.ts +9 -0
- package/dist/adapters/postgresql/resources/vacuum.d.ts.map +1 -0
- package/dist/adapters/postgresql/resources/vacuum.js +122 -0
- package/dist/adapters/postgresql/resources/vacuum.js.map +1 -0
- package/dist/adapters/postgresql/resources/vector.d.ts +9 -0
- package/dist/adapters/postgresql/resources/vector.d.ts.map +1 -0
- package/dist/adapters/postgresql/resources/vector.js +185 -0
- package/dist/adapters/postgresql/resources/vector.js.map +1 -0
- package/dist/adapters/postgresql/schemas/admin.d.ts +74 -0
- package/dist/adapters/postgresql/schemas/admin.d.ts.map +1 -0
- package/dist/adapters/postgresql/schemas/admin.js +180 -0
- package/dist/adapters/postgresql/schemas/admin.js.map +1 -0
- package/dist/adapters/postgresql/schemas/backup.d.ts +68 -0
- package/dist/adapters/postgresql/schemas/backup.d.ts.map +1 -0
- package/dist/adapters/postgresql/schemas/backup.js +114 -0
- package/dist/adapters/postgresql/schemas/backup.js.map +1 -0
- package/dist/adapters/postgresql/schemas/core.d.ts +443 -0
- package/dist/adapters/postgresql/schemas/core.d.ts.map +1 -0
- package/dist/adapters/postgresql/schemas/core.js +628 -0
- package/dist/adapters/postgresql/schemas/core.js.map +1 -0
- package/dist/adapters/postgresql/schemas/cron.d.ts +131 -0
- package/dist/adapters/postgresql/schemas/cron.d.ts.map +1 -0
- package/dist/adapters/postgresql/schemas/cron.js +218 -0
- package/dist/adapters/postgresql/schemas/cron.js.map +1 -0
- package/dist/adapters/postgresql/schemas/extensions.d.ts +403 -0
- package/dist/adapters/postgresql/schemas/extensions.d.ts.map +1 -0
- package/dist/adapters/postgresql/schemas/extensions.js +600 -0
- package/dist/adapters/postgresql/schemas/extensions.js.map +1 -0
- package/dist/adapters/postgresql/schemas/index.d.ts +21 -0
- package/dist/adapters/postgresql/schemas/index.d.ts.map +1 -0
- package/dist/adapters/postgresql/schemas/index.js +72 -0
- package/dist/adapters/postgresql/schemas/index.js.map +1 -0
- package/dist/adapters/postgresql/schemas/jsonb.d.ts +94 -0
- package/dist/adapters/postgresql/schemas/jsonb.d.ts.map +1 -0
- package/dist/adapters/postgresql/schemas/jsonb.js +198 -0
- package/dist/adapters/postgresql/schemas/jsonb.js.map +1 -0
- package/dist/adapters/postgresql/schemas/monitoring.d.ts +28 -0
- package/dist/adapters/postgresql/schemas/monitoring.d.ts.map +1 -0
- package/dist/adapters/postgresql/schemas/monitoring.js +45 -0
- package/dist/adapters/postgresql/schemas/monitoring.js.map +1 -0
- package/dist/adapters/postgresql/schemas/partitioning.d.ts +152 -0
- package/dist/adapters/postgresql/schemas/partitioning.d.ts.map +1 -0
- package/dist/adapters/postgresql/schemas/partitioning.js +399 -0
- package/dist/adapters/postgresql/schemas/partitioning.js.map +1 -0
- package/dist/adapters/postgresql/schemas/partman.d.ts +94 -0
- package/dist/adapters/postgresql/schemas/partman.d.ts.map +1 -0
- package/dist/adapters/postgresql/schemas/partman.js +264 -0
- package/dist/adapters/postgresql/schemas/partman.js.map +1 -0
- package/dist/adapters/postgresql/schemas/performance.d.ts +52 -0
- package/dist/adapters/postgresql/schemas/performance.d.ts.map +1 -0
- package/dist/adapters/postgresql/schemas/performance.js +57 -0
- package/dist/adapters/postgresql/schemas/performance.js.map +1 -0
- package/dist/adapters/postgresql/schemas/postgis.d.ts +693 -0
- package/dist/adapters/postgresql/schemas/postgis.d.ts.map +1 -0
- package/dist/adapters/postgresql/schemas/postgis.js +662 -0
- package/dist/adapters/postgresql/schemas/postgis.js.map +1 -0
- package/dist/adapters/postgresql/schemas/schema-mgmt.d.ts +171 -0
- package/dist/adapters/postgresql/schemas/schema-mgmt.d.ts.map +1 -0
- package/dist/adapters/postgresql/schemas/schema-mgmt.js +235 -0
- package/dist/adapters/postgresql/schemas/schema-mgmt.js.map +1 -0
- package/dist/adapters/postgresql/schemas/stats.d.ts +229 -0
- package/dist/adapters/postgresql/schemas/stats.d.ts.map +1 -0
- package/dist/adapters/postgresql/schemas/stats.js +587 -0
- package/dist/adapters/postgresql/schemas/stats.js.map +1 -0
- package/dist/adapters/postgresql/schemas/text-search.d.ts +83 -0
- package/dist/adapters/postgresql/schemas/text-search.d.ts.map +1 -0
- package/dist/adapters/postgresql/schemas/text-search.js +132 -0
- package/dist/adapters/postgresql/schemas/text-search.js.map +1 -0
- package/dist/adapters/postgresql/schemas/vector.d.ts +143 -0
- package/dist/adapters/postgresql/schemas/vector.d.ts.map +1 -0
- package/dist/adapters/postgresql/schemas/vector.js +123 -0
- package/dist/adapters/postgresql/schemas/vector.js.map +1 -0
- package/dist/adapters/postgresql/tools/admin.d.ts +13 -0
- package/dist/adapters/postgresql/tools/admin.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/admin.js +417 -0
- package/dist/adapters/postgresql/tools/admin.js.map +1 -0
- package/dist/adapters/postgresql/tools/backup/dump.d.ts +12 -0
- package/dist/adapters/postgresql/tools/backup/dump.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/backup/dump.js +546 -0
- package/dist/adapters/postgresql/tools/backup/dump.js.map +1 -0
- package/dist/adapters/postgresql/tools/backup/index.d.ts +16 -0
- package/dist/adapters/postgresql/tools/backup/index.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/backup/index.js +29 -0
- package/dist/adapters/postgresql/tools/backup/index.js.map +1 -0
- package/dist/adapters/postgresql/tools/backup/planning.d.ts +22 -0
- package/dist/adapters/postgresql/tools/backup/planning.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/backup/planning.js +411 -0
- package/dist/adapters/postgresql/tools/backup/planning.js.map +1 -0
- package/dist/adapters/postgresql/tools/citext.d.ts +18 -0
- package/dist/adapters/postgresql/tools/citext.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/citext.js +568 -0
- package/dist/adapters/postgresql/tools/citext.js.map +1 -0
- package/dist/adapters/postgresql/tools/codemode/index.d.ts +27 -0
- package/dist/adapters/postgresql/tools/codemode/index.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/codemode/index.js +171 -0
- package/dist/adapters/postgresql/tools/codemode/index.js.map +1 -0
- package/dist/adapters/postgresql/tools/core/convenience.d.ts +192 -0
- package/dist/adapters/postgresql/tools/core/convenience.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/core/convenience.js +617 -0
- package/dist/adapters/postgresql/tools/core/convenience.js.map +1 -0
- package/dist/adapters/postgresql/tools/core/health.d.ts +20 -0
- package/dist/adapters/postgresql/tools/core/health.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/core/health.js +360 -0
- package/dist/adapters/postgresql/tools/core/health.js.map +1 -0
- package/dist/adapters/postgresql/tools/core/index.d.ts +15 -0
- package/dist/adapters/postgresql/tools/core/index.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/core/index.js +40 -0
- package/dist/adapters/postgresql/tools/core/index.js.map +1 -0
- package/dist/adapters/postgresql/tools/core/indexes.d.ts +30 -0
- package/dist/adapters/postgresql/tools/core/indexes.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/core/indexes.js +232 -0
- package/dist/adapters/postgresql/tools/core/indexes.js.map +1 -0
- package/dist/adapters/postgresql/tools/core/objects.d.ts +20 -0
- package/dist/adapters/postgresql/tools/core/objects.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/core/objects.js +361 -0
- package/dist/adapters/postgresql/tools/core/objects.js.map +1 -0
- package/dist/adapters/postgresql/tools/core/query.d.ts +16 -0
- package/dist/adapters/postgresql/tools/core/query.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/core/query.js +87 -0
- package/dist/adapters/postgresql/tools/core/query.js.map +1 -0
- package/dist/adapters/postgresql/tools/core/schemas.d.ts +135 -0
- package/dist/adapters/postgresql/tools/core/schemas.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/core/schemas.js +221 -0
- package/dist/adapters/postgresql/tools/core/schemas.js.map +1 -0
- package/dist/adapters/postgresql/tools/core/tables.d.ts +24 -0
- package/dist/adapters/postgresql/tools/core/tables.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/core/tables.js +219 -0
- package/dist/adapters/postgresql/tools/core/tables.js.map +1 -0
- package/dist/adapters/postgresql/tools/cron.d.ts +16 -0
- package/dist/adapters/postgresql/tools/cron.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/cron.js +440 -0
- package/dist/adapters/postgresql/tools/cron.js.map +1 -0
- package/dist/adapters/postgresql/tools/jsonb/advanced.d.ts +33 -0
- package/dist/adapters/postgresql/tools/jsonb/advanced.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/jsonb/advanced.js +681 -0
- package/dist/adapters/postgresql/tools/jsonb/advanced.js.map +1 -0
- package/dist/adapters/postgresql/tools/jsonb/basic.d.ts +20 -0
- package/dist/adapters/postgresql/tools/jsonb/basic.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/jsonb/basic.js +654 -0
- package/dist/adapters/postgresql/tools/jsonb/basic.js.map +1 -0
- package/dist/adapters/postgresql/tools/jsonb/index.d.ts +16 -0
- package/dist/adapters/postgresql/tools/jsonb/index.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/jsonb/index.js +39 -0
- package/dist/adapters/postgresql/tools/jsonb/index.js.map +1 -0
- package/dist/adapters/postgresql/tools/kcache.d.ts +20 -0
- package/dist/adapters/postgresql/tools/kcache.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/kcache.js +574 -0
- package/dist/adapters/postgresql/tools/kcache.js.map +1 -0
- package/dist/adapters/postgresql/tools/ltree.d.ts +8 -0
- package/dist/adapters/postgresql/tools/ltree.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/ltree.js +390 -0
- package/dist/adapters/postgresql/tools/ltree.js.map +1 -0
- package/dist/adapters/postgresql/tools/monitoring.d.ts +13 -0
- package/dist/adapters/postgresql/tools/monitoring.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/monitoring.js +753 -0
- package/dist/adapters/postgresql/tools/monitoring.js.map +1 -0
- package/dist/adapters/postgresql/tools/partitioning.d.ts +13 -0
- package/dist/adapters/postgresql/tools/partitioning.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/partitioning.js +500 -0
- package/dist/adapters/postgresql/tools/partitioning.js.map +1 -0
- package/dist/adapters/postgresql/tools/partman/index.d.ts +19 -0
- package/dist/adapters/postgresql/tools/partman/index.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/partman/index.js +33 -0
- package/dist/adapters/postgresql/tools/partman/index.js.map +1 -0
- package/dist/adapters/postgresql/tools/partman/management.d.ts +28 -0
- package/dist/adapters/postgresql/tools/partman/management.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/partman/management.js +563 -0
- package/dist/adapters/postgresql/tools/partman/management.js.map +1 -0
- package/dist/adapters/postgresql/tools/partman/operations.d.ts +28 -0
- package/dist/adapters/postgresql/tools/partman/operations.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/partman/operations.js +632 -0
- package/dist/adapters/postgresql/tools/partman/operations.js.map +1 -0
- package/dist/adapters/postgresql/tools/performance/analysis.d.ts +9 -0
- package/dist/adapters/postgresql/tools/performance/analysis.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/performance/analysis.js +383 -0
- package/dist/adapters/postgresql/tools/performance/analysis.js.map +1 -0
- package/dist/adapters/postgresql/tools/performance/explain.d.ts +13 -0
- package/dist/adapters/postgresql/tools/performance/explain.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/performance/explain.js +71 -0
- package/dist/adapters/postgresql/tools/performance/explain.js.map +1 -0
- package/dist/adapters/postgresql/tools/performance/index.d.ts +13 -0
- package/dist/adapters/postgresql/tools/performance/index.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/performance/index.js +40 -0
- package/dist/adapters/postgresql/tools/performance/index.js.map +1 -0
- package/dist/adapters/postgresql/tools/performance/monitoring.d.ts +9 -0
- package/dist/adapters/postgresql/tools/performance/monitoring.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/performance/monitoring.js +122 -0
- package/dist/adapters/postgresql/tools/performance/monitoring.js.map +1 -0
- package/dist/adapters/postgresql/tools/performance/optimization.d.ts +9 -0
- package/dist/adapters/postgresql/tools/performance/optimization.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/performance/optimization.js +315 -0
- package/dist/adapters/postgresql/tools/performance/optimization.js.map +1 -0
- package/dist/adapters/postgresql/tools/performance/stats.d.ts +14 -0
- package/dist/adapters/postgresql/tools/performance/stats.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/performance/stats.js +559 -0
- package/dist/adapters/postgresql/tools/performance/stats.js.map +1 -0
- package/dist/adapters/postgresql/tools/pgcrypto.d.ts +8 -0
- package/dist/adapters/postgresql/tools/pgcrypto.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/pgcrypto.js +239 -0
- package/dist/adapters/postgresql/tools/pgcrypto.js.map +1 -0
- package/dist/adapters/postgresql/tools/postgis/advanced.d.ts +21 -0
- package/dist/adapters/postgresql/tools/postgis/advanced.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/postgis/advanced.js +383 -0
- package/dist/adapters/postgresql/tools/postgis/advanced.js.map +1 -0
- package/dist/adapters/postgresql/tools/postgis/basic.d.ts +16 -0
- package/dist/adapters/postgresql/tools/postgis/basic.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/postgis/basic.js +479 -0
- package/dist/adapters/postgresql/tools/postgis/basic.js.map +1 -0
- package/dist/adapters/postgresql/tools/postgis/index.d.ts +17 -0
- package/dist/adapters/postgresql/tools/postgis/index.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/postgis/index.js +46 -0
- package/dist/adapters/postgresql/tools/postgis/index.js.map +1 -0
- package/dist/adapters/postgresql/tools/postgis/standalone.d.ts +21 -0
- package/dist/adapters/postgresql/tools/postgis/standalone.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/postgis/standalone.js +150 -0
- package/dist/adapters/postgresql/tools/postgis/standalone.js.map +1 -0
- package/dist/adapters/postgresql/tools/schema.d.ts +13 -0
- package/dist/adapters/postgresql/tools/schema.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/schema.js +515 -0
- package/dist/adapters/postgresql/tools/schema.js.map +1 -0
- package/dist/adapters/postgresql/tools/stats/advanced.d.ts +24 -0
- package/dist/adapters/postgresql/tools/stats/advanced.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/stats/advanced.js +876 -0
- package/dist/adapters/postgresql/tools/stats/advanced.js.map +1 -0
- package/dist/adapters/postgresql/tools/stats/basic.d.ts +24 -0
- package/dist/adapters/postgresql/tools/stats/basic.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/stats/basic.js +501 -0
- package/dist/adapters/postgresql/tools/stats/basic.js.map +1 -0
- package/dist/adapters/postgresql/tools/stats/index.d.ts +17 -0
- package/dist/adapters/postgresql/tools/stats/index.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/stats/index.js +30 -0
- package/dist/adapters/postgresql/tools/stats/index.js.map +1 -0
- package/dist/adapters/postgresql/tools/text.d.ts +13 -0
- package/dist/adapters/postgresql/tools/text.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/text.js +708 -0
- package/dist/adapters/postgresql/tools/text.js.map +1 -0
- package/dist/adapters/postgresql/tools/transactions.d.ts +13 -0
- package/dist/adapters/postgresql/tools/transactions.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/transactions.js +201 -0
- package/dist/adapters/postgresql/tools/transactions.js.map +1 -0
- package/dist/adapters/postgresql/tools/vector/advanced.d.ts +12 -0
- package/dist/adapters/postgresql/tools/vector/advanced.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/vector/advanced.js +902 -0
- package/dist/adapters/postgresql/tools/vector/advanced.js.map +1 -0
- package/dist/adapters/postgresql/tools/vector/basic.d.ts +25 -0
- package/dist/adapters/postgresql/tools/vector/basic.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/vector/basic.js +1000 -0
- package/dist/adapters/postgresql/tools/vector/basic.js.map +1 -0
- package/dist/adapters/postgresql/tools/vector/index.d.ts +13 -0
- package/dist/adapters/postgresql/tools/vector/index.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/vector/index.js +33 -0
- package/dist/adapters/postgresql/tools/vector/index.js.map +1 -0
- package/dist/auth/AuthorizationServerDiscovery.d.ts +44 -0
- package/dist/auth/AuthorizationServerDiscovery.d.ts.map +1 -0
- package/dist/auth/AuthorizationServerDiscovery.js +117 -0
- package/dist/auth/AuthorizationServerDiscovery.js.map +1 -0
- package/dist/auth/OAuthResourceServer.d.ts +42 -0
- package/dist/auth/OAuthResourceServer.d.ts.map +1 -0
- package/dist/auth/OAuthResourceServer.js +80 -0
- package/dist/auth/OAuthResourceServer.js.map +1 -0
- package/dist/auth/TokenValidator.d.ts +36 -0
- package/dist/auth/TokenValidator.d.ts.map +1 -0
- package/dist/auth/TokenValidator.js +139 -0
- package/dist/auth/TokenValidator.js.map +1 -0
- package/dist/auth/errors.d.ts +63 -0
- package/dist/auth/errors.d.ts.map +1 -0
- package/dist/auth/errors.js +102 -0
- package/dist/auth/errors.js.map +1 -0
- package/dist/auth/index.d.ts +15 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +16 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/middleware.d.ts +61 -0
- package/dist/auth/middleware.d.ts.map +1 -0
- package/dist/auth/middleware.js +156 -0
- package/dist/auth/middleware.js.map +1 -0
- package/dist/auth/scopes.d.ts +65 -0
- package/dist/auth/scopes.d.ts.map +1 -0
- package/dist/auth/scopes.js +189 -0
- package/dist/auth/scopes.js.map +1 -0
- package/dist/auth/types.d.ts +208 -0
- package/dist/auth/types.d.ts.map +1 -0
- package/dist/auth/types.js +8 -0
- package/dist/auth/types.js.map +1 -0
- package/dist/cli/args.d.ts +34 -0
- package/dist/cli/args.d.ts.map +1 -0
- package/dist/cli/args.js +308 -0
- package/dist/cli/args.js.map +1 -0
- package/dist/cli/index.d.ts +8 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +7 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli.d.ts +9 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +341 -0
- package/dist/cli.js.map +1 -0
- package/dist/codemode/api.d.ts +62 -0
- package/dist/codemode/api.d.ts.map +1 -0
- package/dist/codemode/api.js +1505 -0
- package/dist/codemode/api.js.map +1 -0
- package/dist/codemode/index.d.ts +13 -0
- package/dist/codemode/index.d.ts.map +1 -0
- package/dist/codemode/index.js +17 -0
- package/dist/codemode/index.js.map +1 -0
- package/dist/codemode/sandbox-factory.d.ts +72 -0
- package/dist/codemode/sandbox-factory.d.ts.map +1 -0
- package/dist/codemode/sandbox-factory.js +88 -0
- package/dist/codemode/sandbox-factory.js.map +1 -0
- package/dist/codemode/sandbox.d.ts +96 -0
- package/dist/codemode/sandbox.d.ts.map +1 -0
- package/dist/codemode/sandbox.js +345 -0
- package/dist/codemode/sandbox.js.map +1 -0
- package/dist/codemode/security.d.ts +44 -0
- package/dist/codemode/security.d.ts.map +1 -0
- package/dist/codemode/security.js +149 -0
- package/dist/codemode/security.js.map +1 -0
- package/dist/codemode/types.d.ts +137 -0
- package/dist/codemode/types.d.ts.map +1 -0
- package/dist/codemode/types.js +46 -0
- package/dist/codemode/types.js.map +1 -0
- package/dist/codemode/worker-sandbox.d.ts +82 -0
- package/dist/codemode/worker-sandbox.d.ts.map +1 -0
- package/dist/codemode/worker-sandbox.js +244 -0
- package/dist/codemode/worker-sandbox.js.map +1 -0
- package/dist/codemode/worker-script.d.ts +8 -0
- package/dist/codemode/worker-script.d.ts.map +1 -0
- package/dist/codemode/worker-script.js +113 -0
- package/dist/codemode/worker-script.js.map +1 -0
- package/dist/constants/ServerInstructions.d.ts +13 -0
- package/dist/constants/ServerInstructions.d.ts.map +1 -0
- package/dist/constants/ServerInstructions.js +405 -0
- package/dist/constants/ServerInstructions.js.map +1 -0
- package/dist/filtering/ToolConstants.d.ts +43 -0
- package/dist/filtering/ToolConstants.d.ts.map +1 -0
- package/dist/filtering/ToolConstants.js +352 -0
- package/dist/filtering/ToolConstants.js.map +1 -0
- package/dist/filtering/ToolFilter.d.ts +90 -0
- package/dist/filtering/ToolFilter.d.ts.map +1 -0
- package/dist/filtering/ToolFilter.js +315 -0
- package/dist/filtering/ToolFilter.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/pool/ConnectionPool.d.ts +70 -0
- package/dist/pool/ConnectionPool.d.ts.map +1 -0
- package/dist/pool/ConnectionPool.js +254 -0
- package/dist/pool/ConnectionPool.js.map +1 -0
- package/dist/server/McpServer.d.ts +50 -0
- package/dist/server/McpServer.d.ts.map +1 -0
- package/dist/server/McpServer.js +108 -0
- package/dist/server/McpServer.js.map +1 -0
- package/dist/transports/http.d.ts +126 -0
- package/dist/transports/http.d.ts.map +1 -0
- package/dist/transports/http.js +303 -0
- package/dist/transports/http.js.map +1 -0
- package/dist/transports/index.d.ts +8 -0
- package/dist/transports/index.d.ts.map +1 -0
- package/dist/transports/index.js +7 -0
- package/dist/transports/index.js.map +1 -0
- package/dist/types/adapters.d.ts +136 -0
- package/dist/types/adapters.d.ts.map +1 -0
- package/dist/types/adapters.js +7 -0
- package/dist/types/adapters.js.map +1 -0
- package/dist/types/database.d.ts +204 -0
- package/dist/types/database.d.ts.map +1 -0
- package/dist/types/database.js +7 -0
- package/dist/types/database.js.map +1 -0
- package/dist/types/errors.d.ts +62 -0
- package/dist/types/errors.d.ts.map +1 -0
- package/dist/types/errors.js +91 -0
- package/dist/types/errors.js.map +1 -0
- package/dist/types/filtering.d.ts +39 -0
- package/dist/types/filtering.d.ts.map +1 -0
- package/dist/types/filtering.js +7 -0
- package/dist/types/filtering.js.map +1 -0
- package/dist/types/index.d.ts +16 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +11 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/mcp.d.ts +31 -0
- package/dist/types/mcp.d.ts.map +1 -0
- package/dist/types/mcp.js +7 -0
- package/dist/types/mcp.js.map +1 -0
- package/dist/types/oauth.d.ts +65 -0
- package/dist/types/oauth.d.ts.map +1 -0
- package/dist/types/oauth.js +7 -0
- package/dist/types/oauth.js.map +1 -0
- package/dist/types/schema.d.ts +110 -0
- package/dist/types/schema.d.ts.map +1 -0
- package/dist/types/schema.js +7 -0
- package/dist/types/schema.js.map +1 -0
- package/dist/utils/annotations.d.ts +42 -0
- package/dist/utils/annotations.d.ts.map +1 -0
- package/dist/utils/annotations.js +75 -0
- package/dist/utils/annotations.js.map +1 -0
- package/dist/utils/icons.d.ts +25 -0
- package/dist/utils/icons.d.ts.map +1 -0
- package/dist/utils/icons.js +212 -0
- package/dist/utils/icons.js.map +1 -0
- package/dist/utils/identifiers.d.ts +111 -0
- package/dist/utils/identifiers.d.ts.map +1 -0
- package/dist/utils/identifiers.js +270 -0
- package/dist/utils/identifiers.js.map +1 -0
- package/dist/utils/logger.d.ts +141 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +304 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/promptGenerator.d.ts +20 -0
- package/dist/utils/promptGenerator.d.ts.map +1 -0
- package/dist/utils/promptGenerator.js +81 -0
- package/dist/utils/promptGenerator.js.map +1 -0
- package/dist/utils/resourceAnnotations.d.ts +36 -0
- package/dist/utils/resourceAnnotations.d.ts.map +1 -0
- package/dist/utils/resourceAnnotations.js +57 -0
- package/dist/utils/resourceAnnotations.js.map +1 -0
- package/package.json +64 -0
|
@@ -0,0 +1,876 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PostgreSQL Statistics Tools - Advanced Statistics
|
|
3
|
+
*
|
|
4
|
+
* Advanced statistical analysis tools: time series, distribution, hypothesis testing, sampling.
|
|
5
|
+
*/
|
|
6
|
+
import { readOnly } from "../../../../utils/annotations.js";
|
|
7
|
+
import { getToolIcons } from "../../../../utils/icons.js";
|
|
8
|
+
import {
|
|
9
|
+
// Base schemas for MCP visibility
|
|
10
|
+
StatsTimeSeriesSchemaBase, StatsDistributionSchemaBase, StatsHypothesisSchemaBase, StatsSamplingSchemaBase,
|
|
11
|
+
// Preprocessed schemas for handler parsing
|
|
12
|
+
StatsTimeSeriesSchema, StatsDistributionSchema, StatsHypothesisSchema, StatsSamplingSchema, } from "../../schemas/index.js";
|
|
13
|
+
// =============================================================================
|
|
14
|
+
// P-Value Calculation Utilities
|
|
15
|
+
// =============================================================================
|
|
16
|
+
/**
|
|
17
|
+
* Log gamma function using Lanczos approximation.
|
|
18
|
+
* Used for computing the incomplete beta function.
|
|
19
|
+
*/
|
|
20
|
+
function logGamma(x) {
|
|
21
|
+
// Lanczos coefficients (truncated to 14 significant digits for JS precision)
|
|
22
|
+
const c0 = 76.18009172947;
|
|
23
|
+
const c1 = -86.50532032942;
|
|
24
|
+
const c2 = 24.01409824083;
|
|
25
|
+
const c3 = -1.2317395724502;
|
|
26
|
+
const c4 = 0.0012086509738662;
|
|
27
|
+
const c5 = -0.000005395239385;
|
|
28
|
+
let y = x;
|
|
29
|
+
let tmp = x + 5.5;
|
|
30
|
+
tmp -= (x + 0.5) * Math.log(tmp);
|
|
31
|
+
let ser = 1.000000000190015;
|
|
32
|
+
y += 1;
|
|
33
|
+
ser += c0 / y;
|
|
34
|
+
y += 1;
|
|
35
|
+
ser += c1 / y;
|
|
36
|
+
y += 1;
|
|
37
|
+
ser += c2 / y;
|
|
38
|
+
y += 1;
|
|
39
|
+
ser += c3 / y;
|
|
40
|
+
y += 1;
|
|
41
|
+
ser += c4 / y;
|
|
42
|
+
y += 1;
|
|
43
|
+
ser += c5 / y;
|
|
44
|
+
return -tmp + Math.log((2.506628274631 * ser) / x);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Regularized incomplete beta function using continued fraction expansion.
|
|
48
|
+
* I_x(a,b) = B_x(a,b) / B(a,b)
|
|
49
|
+
*
|
|
50
|
+
* This is used to compute the CDF of the t-distribution.
|
|
51
|
+
*/
|
|
52
|
+
function incompleteBeta(a, b, x) {
|
|
53
|
+
if (x <= 0)
|
|
54
|
+
return 0;
|
|
55
|
+
if (x >= 1)
|
|
56
|
+
return 1;
|
|
57
|
+
// Use symmetry relation if x > (a+1)/(a+b+2)
|
|
58
|
+
if (x > (a + 1) / (a + b + 2)) {
|
|
59
|
+
return 1 - incompleteBeta(b, a, 1 - x);
|
|
60
|
+
}
|
|
61
|
+
// Compute the prefactor
|
|
62
|
+
const lnBeta = logGamma(a) + logGamma(b) - logGamma(a + b);
|
|
63
|
+
const front = Math.exp(Math.log(x) * a + Math.log(1 - x) * b - lnBeta - Math.log(a));
|
|
64
|
+
// Lentz's algorithm for continued fraction
|
|
65
|
+
const maxIterations = 200;
|
|
66
|
+
const epsilon = 1e-14;
|
|
67
|
+
const tiny = 1e-30;
|
|
68
|
+
let c = 1;
|
|
69
|
+
let d = 1 - ((a + b) * x) / (a + 1);
|
|
70
|
+
if (Math.abs(d) < tiny)
|
|
71
|
+
d = tiny;
|
|
72
|
+
d = 1 / d;
|
|
73
|
+
let h = d;
|
|
74
|
+
for (let m = 1; m <= maxIterations; m++) {
|
|
75
|
+
const m2 = 2 * m;
|
|
76
|
+
// Even step
|
|
77
|
+
let aa = (m * (b - m) * x) / ((a + m2 - 1) * (a + m2));
|
|
78
|
+
d = 1 + aa * d;
|
|
79
|
+
if (Math.abs(d) < tiny)
|
|
80
|
+
d = tiny;
|
|
81
|
+
c = 1 + aa / c;
|
|
82
|
+
if (Math.abs(c) < tiny)
|
|
83
|
+
c = tiny;
|
|
84
|
+
d = 1 / d;
|
|
85
|
+
h *= d * c;
|
|
86
|
+
// Odd step
|
|
87
|
+
aa = -((a + m) * (a + b + m) * x) / ((a + m2) * (a + m2 + 1));
|
|
88
|
+
d = 1 + aa * d;
|
|
89
|
+
if (Math.abs(d) < tiny)
|
|
90
|
+
d = tiny;
|
|
91
|
+
c = 1 + aa / c;
|
|
92
|
+
if (Math.abs(c) < tiny)
|
|
93
|
+
c = tiny;
|
|
94
|
+
d = 1 / d;
|
|
95
|
+
const delta = d * c;
|
|
96
|
+
h *= delta;
|
|
97
|
+
if (Math.abs(delta - 1) < epsilon)
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
100
|
+
return front * h;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Cumulative distribution function for the t-distribution.
|
|
104
|
+
* Uses the relationship between t-distribution and incomplete beta function.
|
|
105
|
+
*
|
|
106
|
+
* @param t - The t-statistic
|
|
107
|
+
* @param df - Degrees of freedom
|
|
108
|
+
* @returns Probability P(T <= t) for a t-distributed random variable
|
|
109
|
+
*/
|
|
110
|
+
function tDistributionCDF(t, df) {
|
|
111
|
+
const x = df / (df + t * t);
|
|
112
|
+
const beta = incompleteBeta(df / 2, 0.5, x);
|
|
113
|
+
if (t >= 0) {
|
|
114
|
+
return 1 - 0.5 * beta;
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
return 0.5 * beta;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Calculate two-tailed p-value for a t-test.
|
|
122
|
+
*
|
|
123
|
+
* @param t - The t-statistic
|
|
124
|
+
* @param df - Degrees of freedom
|
|
125
|
+
* @returns Two-tailed p-value
|
|
126
|
+
*/
|
|
127
|
+
function calculateTTestPValue(t, df) {
|
|
128
|
+
// Two-tailed: P(|T| > |t|) = 2 * P(T > |t|) = 2 * (1 - CDF(|t|))
|
|
129
|
+
const absT = Math.abs(t);
|
|
130
|
+
return 2 * (1 - tDistributionCDF(absT, df));
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Cumulative distribution function for the standard normal distribution.
|
|
134
|
+
* Uses the error function approximation.
|
|
135
|
+
*
|
|
136
|
+
* @param z - The z-statistic
|
|
137
|
+
* @returns Probability P(Z <= z) for a standard normal random variable
|
|
138
|
+
*/
|
|
139
|
+
function normalCDF(z) {
|
|
140
|
+
// Approximation using the error function
|
|
141
|
+
const a1 = 0.254829592;
|
|
142
|
+
const a2 = -0.284496736;
|
|
143
|
+
const a3 = 1.421413741;
|
|
144
|
+
const a4 = -1.453152027;
|
|
145
|
+
const a5 = 1.061405429;
|
|
146
|
+
const p = 0.3275911;
|
|
147
|
+
const sign = z < 0 ? -1 : 1;
|
|
148
|
+
const x = Math.abs(z) / Math.sqrt(2);
|
|
149
|
+
const t = 1 / (1 + p * x);
|
|
150
|
+
const y = 1 - ((((a5 * t + a4) * t + a3) * t + a2) * t + a1) * t * Math.exp(-x * x);
|
|
151
|
+
return 0.5 * (1 + sign * y);
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Calculate two-tailed p-value for a z-test.
|
|
155
|
+
*
|
|
156
|
+
* @param z - The z-statistic
|
|
157
|
+
* @returns Two-tailed p-value
|
|
158
|
+
*/
|
|
159
|
+
function calculateZTestPValue(z) {
|
|
160
|
+
// Two-tailed: P(|Z| > |z|) = 2 * P(Z > |z|) = 2 * (1 - CDF(|z|))
|
|
161
|
+
const absZ = Math.abs(z);
|
|
162
|
+
return 2 * (1 - normalCDF(absZ));
|
|
163
|
+
}
|
|
164
|
+
// =============================================================================
|
|
165
|
+
// Validation Helpers
|
|
166
|
+
// =============================================================================
|
|
167
|
+
/**
|
|
168
|
+
* Validate that a table exists and a column is numeric.
|
|
169
|
+
* Throws user-friendly error messages for missing table/column.
|
|
170
|
+
*/
|
|
171
|
+
async function validateNumericColumn(adapter, table, column, schema) {
|
|
172
|
+
const numericTypes = [
|
|
173
|
+
"integer",
|
|
174
|
+
"bigint",
|
|
175
|
+
"smallint",
|
|
176
|
+
"numeric",
|
|
177
|
+
"decimal",
|
|
178
|
+
"real",
|
|
179
|
+
"double precision",
|
|
180
|
+
"money",
|
|
181
|
+
];
|
|
182
|
+
const typeCheckQuery = `
|
|
183
|
+
SELECT data_type
|
|
184
|
+
FROM information_schema.columns
|
|
185
|
+
WHERE table_schema = '${schema}'
|
|
186
|
+
AND table_name = '${table}'
|
|
187
|
+
AND column_name = '${column}'
|
|
188
|
+
`;
|
|
189
|
+
const typeResult = await adapter.executeQuery(typeCheckQuery);
|
|
190
|
+
const typeRow = typeResult.rows?.[0];
|
|
191
|
+
if (!typeRow) {
|
|
192
|
+
// Check if table exists
|
|
193
|
+
const tableCheckQuery = `
|
|
194
|
+
SELECT 1 FROM information_schema.tables
|
|
195
|
+
WHERE table_schema = '${schema}' AND table_name = '${table}'
|
|
196
|
+
`;
|
|
197
|
+
const tableResult = await adapter.executeQuery(tableCheckQuery);
|
|
198
|
+
if (tableResult.rows?.length === 0) {
|
|
199
|
+
throw new Error(`Table "${schema}.${table}" not found`);
|
|
200
|
+
}
|
|
201
|
+
throw new Error(`Column "${column}" not found in table "${schema}.${table}"`);
|
|
202
|
+
}
|
|
203
|
+
if (!numericTypes.includes(typeRow.data_type)) {
|
|
204
|
+
throw new Error(`Column "${column}" is type "${typeRow.data_type}" but must be a numeric type for statistical analysis`);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Validate that a table exists (for tools that don't require a specific column).
|
|
209
|
+
* Throws user-friendly error message for missing table.
|
|
210
|
+
*/
|
|
211
|
+
async function validateTableExists(adapter, table, schema) {
|
|
212
|
+
const tableCheckQuery = `
|
|
213
|
+
SELECT 1 FROM information_schema.tables
|
|
214
|
+
WHERE table_schema = '${schema}' AND table_name = '${table}'
|
|
215
|
+
`;
|
|
216
|
+
const tableResult = await adapter.executeQuery(tableCheckQuery);
|
|
217
|
+
if (tableResult.rows?.length === 0) {
|
|
218
|
+
throw new Error(`Table "${schema}.${table}" not found`);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
// =============================================================================
|
|
222
|
+
// Tool Implementations
|
|
223
|
+
// =============================================================================
|
|
224
|
+
/**
|
|
225
|
+
* Time series analysis
|
|
226
|
+
*/
|
|
227
|
+
export function createStatsTimeSeriesTool(adapter) {
|
|
228
|
+
return {
|
|
229
|
+
name: "pg_stats_time_series",
|
|
230
|
+
description: "Aggregate data into time buckets for time series analysis. Use groupBy to get separate time series per category.",
|
|
231
|
+
group: "stats",
|
|
232
|
+
inputSchema: StatsTimeSeriesSchemaBase, // Base schema for MCP visibility
|
|
233
|
+
annotations: readOnly("Time Series Analysis"),
|
|
234
|
+
icons: getToolIcons("stats", readOnly("Time Series Analysis")),
|
|
235
|
+
handler: async (params, _context) => {
|
|
236
|
+
const { table, valueColumn, timeColumn, interval, aggregation, schema, where, limit, groupBy, groupLimit, } = StatsTimeSeriesSchema.parse(params);
|
|
237
|
+
const schemaPrefix = schema ? `"${schema}".` : "";
|
|
238
|
+
const whereClause = where ? `WHERE ${where}` : "";
|
|
239
|
+
const agg = aggregation ?? "avg";
|
|
240
|
+
// Handle limit: undefined uses default (100), 0 means no limit
|
|
241
|
+
// Track whether user explicitly provided a limit
|
|
242
|
+
const userProvidedLimit = limit !== undefined;
|
|
243
|
+
const DEFAULT_LIMIT = 100;
|
|
244
|
+
// limit === 0 means "no limit", otherwise use provided limit or default
|
|
245
|
+
const effectiveLimit = limit === 0 ? undefined : (limit ?? DEFAULT_LIMIT);
|
|
246
|
+
const usingDefaultLimit = !userProvidedLimit && effectiveLimit !== undefined;
|
|
247
|
+
// First check if table exists
|
|
248
|
+
const schemaName = schema ?? "public";
|
|
249
|
+
const tableCheckQuery = `
|
|
250
|
+
SELECT 1 FROM information_schema.tables
|
|
251
|
+
WHERE table_schema = '${schemaName}' AND table_name = '${table}'
|
|
252
|
+
`;
|
|
253
|
+
const tableCheckResult = await adapter.executeQuery(tableCheckQuery);
|
|
254
|
+
if (tableCheckResult.rows?.length === 0) {
|
|
255
|
+
throw new Error(`Table "${schemaName}.${table}" not found`);
|
|
256
|
+
}
|
|
257
|
+
// Validate timeColumn is a timestamp/date type
|
|
258
|
+
const typeCheckQuery = `
|
|
259
|
+
SELECT data_type
|
|
260
|
+
FROM information_schema.columns
|
|
261
|
+
WHERE table_schema = '${schemaName}'
|
|
262
|
+
AND table_name = '${table}'
|
|
263
|
+
AND column_name = '${timeColumn}'
|
|
264
|
+
`;
|
|
265
|
+
const typeResult = await adapter.executeQuery(typeCheckQuery);
|
|
266
|
+
const typeRow = typeResult.rows?.[0];
|
|
267
|
+
if (!typeRow) {
|
|
268
|
+
throw new Error(`Column "${timeColumn}" not found in table "${schemaName}.${table}"`);
|
|
269
|
+
}
|
|
270
|
+
const validTypes = [
|
|
271
|
+
"timestamp without time zone",
|
|
272
|
+
"timestamp with time zone",
|
|
273
|
+
"date",
|
|
274
|
+
"time",
|
|
275
|
+
"time without time zone",
|
|
276
|
+
"time with time zone",
|
|
277
|
+
];
|
|
278
|
+
if (!validTypes.includes(typeRow.data_type)) {
|
|
279
|
+
throw new Error(`Column "${timeColumn}" is type "${typeRow.data_type}" but must be a timestamp or date type for time series analysis`);
|
|
280
|
+
}
|
|
281
|
+
// Note: schemaName already defined above for table check
|
|
282
|
+
// Validate valueColumn exists and is numeric
|
|
283
|
+
const numericTypes = [
|
|
284
|
+
"integer",
|
|
285
|
+
"bigint",
|
|
286
|
+
"smallint",
|
|
287
|
+
"numeric",
|
|
288
|
+
"decimal",
|
|
289
|
+
"real",
|
|
290
|
+
"double precision",
|
|
291
|
+
"money",
|
|
292
|
+
];
|
|
293
|
+
const valueTypeQuery = `
|
|
294
|
+
SELECT data_type
|
|
295
|
+
FROM information_schema.columns
|
|
296
|
+
WHERE table_schema = '${schemaName}'
|
|
297
|
+
AND table_name = '${table}'
|
|
298
|
+
AND column_name = '${valueColumn}'
|
|
299
|
+
`;
|
|
300
|
+
const valueTypeResult = await adapter.executeQuery(valueTypeQuery);
|
|
301
|
+
const valueTypeRow = valueTypeResult.rows?.[0];
|
|
302
|
+
if (!valueTypeRow) {
|
|
303
|
+
throw new Error(`Column "${valueColumn}" not found in table "${schemaName}.${table}"`);
|
|
304
|
+
}
|
|
305
|
+
if (!numericTypes.includes(valueTypeRow.data_type)) {
|
|
306
|
+
throw new Error(`Column "${valueColumn}" is type "${valueTypeRow.data_type}" but must be a numeric type for time series aggregation`);
|
|
307
|
+
}
|
|
308
|
+
// Helper to map bucket row
|
|
309
|
+
const mapBucket = (row) => ({
|
|
310
|
+
timeBucket: row["time_bucket"],
|
|
311
|
+
value: Number(row["value"]),
|
|
312
|
+
count: Number(row["count"]),
|
|
313
|
+
});
|
|
314
|
+
if (groupBy !== undefined) {
|
|
315
|
+
// Handle groupLimit: undefined uses default (20), 0 means no limit
|
|
316
|
+
const DEFAULT_GROUP_LIMIT = 20;
|
|
317
|
+
const userProvidedGroupLimit = groupLimit !== undefined;
|
|
318
|
+
const effectiveGroupLimit = groupLimit === 0 ? undefined : (groupLimit ?? DEFAULT_GROUP_LIMIT);
|
|
319
|
+
// First get total count of distinct groups for truncation indicator
|
|
320
|
+
const groupCountSql = `
|
|
321
|
+
SELECT COUNT(DISTINCT "${groupBy}") as total_groups
|
|
322
|
+
FROM ${schemaPrefix}"${table}"
|
|
323
|
+
${whereClause}
|
|
324
|
+
`;
|
|
325
|
+
const groupCountResult = await adapter.executeQuery(groupCountSql);
|
|
326
|
+
const totalGroupCount = Number(groupCountResult.rows?.[0]
|
|
327
|
+
?.total_groups ?? 0);
|
|
328
|
+
// Grouped time series
|
|
329
|
+
const sql = `
|
|
330
|
+
SELECT
|
|
331
|
+
"${groupBy}" as group_key,
|
|
332
|
+
DATE_TRUNC('${interval}', "${timeColumn}") as time_bucket,
|
|
333
|
+
${agg.toUpperCase()}("${valueColumn}")::numeric(20,6) as value,
|
|
334
|
+
COUNT(*) as count
|
|
335
|
+
FROM ${schemaPrefix}"${table}"
|
|
336
|
+
${whereClause}
|
|
337
|
+
GROUP BY "${groupBy}", DATE_TRUNC('${interval}', "${timeColumn}")
|
|
338
|
+
ORDER BY "${groupBy}", time_bucket DESC
|
|
339
|
+
`;
|
|
340
|
+
const result = await adapter.executeQuery(sql);
|
|
341
|
+
const rows = result.rows ?? [];
|
|
342
|
+
// Group results by group_key
|
|
343
|
+
const groupsMap = new Map();
|
|
344
|
+
const groupsTotalCount = new Map();
|
|
345
|
+
let groupsProcessed = 0;
|
|
346
|
+
for (const row of rows) {
|
|
347
|
+
const key = row["group_key"];
|
|
348
|
+
if (!groupsMap.has(key)) {
|
|
349
|
+
// Check if we've hit the group limit
|
|
350
|
+
if (effectiveGroupLimit !== undefined &&
|
|
351
|
+
groupsProcessed >= effectiveGroupLimit) {
|
|
352
|
+
continue;
|
|
353
|
+
}
|
|
354
|
+
groupsMap.set(key, []);
|
|
355
|
+
groupsTotalCount.set(key, 0);
|
|
356
|
+
groupsProcessed++;
|
|
357
|
+
}
|
|
358
|
+
const currentTotal = groupsTotalCount.get(key) ?? 0;
|
|
359
|
+
groupsTotalCount.set(key, currentTotal + 1);
|
|
360
|
+
const bucketList = groupsMap.get(key);
|
|
361
|
+
// Only add if no limit or under limit
|
|
362
|
+
if (bucketList !== undefined &&
|
|
363
|
+
(effectiveLimit === undefined || bucketList.length < effectiveLimit)) {
|
|
364
|
+
bucketList.push(mapBucket(row));
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
const groups = Array.from(groupsMap.entries()).map(([key, buckets]) => ({
|
|
368
|
+
groupKey: key,
|
|
369
|
+
buckets,
|
|
370
|
+
}));
|
|
371
|
+
// Build response with truncation indicators
|
|
372
|
+
const response = {
|
|
373
|
+
table: `${schema ?? "public"}.${table}`,
|
|
374
|
+
valueColumn,
|
|
375
|
+
timeColumn,
|
|
376
|
+
interval,
|
|
377
|
+
aggregation: agg,
|
|
378
|
+
groupBy,
|
|
379
|
+
groups,
|
|
380
|
+
count: groups.length,
|
|
381
|
+
};
|
|
382
|
+
// Add truncation indicators when groups are limited
|
|
383
|
+
const groupsTruncated = effectiveGroupLimit !== undefined &&
|
|
384
|
+
totalGroupCount > effectiveGroupLimit;
|
|
385
|
+
if (groupsTruncated || !userProvidedGroupLimit) {
|
|
386
|
+
response["truncated"] = groupsTruncated;
|
|
387
|
+
response["totalGroupCount"] = totalGroupCount;
|
|
388
|
+
}
|
|
389
|
+
return response;
|
|
390
|
+
}
|
|
391
|
+
// Ungrouped time series
|
|
392
|
+
// Build LIMIT clause: no LIMIT if effectiveLimit is undefined (limit: 0)
|
|
393
|
+
const limitClause = effectiveLimit !== undefined ? `LIMIT ${String(effectiveLimit)}` : "";
|
|
394
|
+
// Get total count if using default limit (for truncation indicator)
|
|
395
|
+
let totalCount;
|
|
396
|
+
if (usingDefaultLimit) {
|
|
397
|
+
const countSql = `
|
|
398
|
+
SELECT COUNT(DISTINCT DATE_TRUNC('${interval}', "${timeColumn}")) as total_buckets
|
|
399
|
+
FROM ${schemaPrefix}"${table}"
|
|
400
|
+
${whereClause}
|
|
401
|
+
`;
|
|
402
|
+
const countResult = await adapter.executeQuery(countSql);
|
|
403
|
+
const countRow = countResult.rows?.[0];
|
|
404
|
+
totalCount = countRow ? Number(countRow.total_buckets) : undefined;
|
|
405
|
+
}
|
|
406
|
+
const sql = `
|
|
407
|
+
SELECT
|
|
408
|
+
DATE_TRUNC('${interval}', "${timeColumn}") as time_bucket,
|
|
409
|
+
${agg.toUpperCase()}("${valueColumn}")::numeric(20,6) as value,
|
|
410
|
+
COUNT(*) as count
|
|
411
|
+
FROM ${schemaPrefix}"${table}"
|
|
412
|
+
${whereClause}
|
|
413
|
+
GROUP BY DATE_TRUNC('${interval}', "${timeColumn}")
|
|
414
|
+
ORDER BY time_bucket DESC
|
|
415
|
+
${limitClause}
|
|
416
|
+
`;
|
|
417
|
+
const result = await adapter.executeQuery(sql);
|
|
418
|
+
const buckets = (result.rows ?? []).map((row) => mapBucket(row));
|
|
419
|
+
// Build response
|
|
420
|
+
const response = {
|
|
421
|
+
table: `${schema ?? "public"}.${table}`,
|
|
422
|
+
valueColumn,
|
|
423
|
+
timeColumn,
|
|
424
|
+
interval,
|
|
425
|
+
aggregation: agg,
|
|
426
|
+
buckets,
|
|
427
|
+
};
|
|
428
|
+
// Add truncation indicators when default limit was applied
|
|
429
|
+
if (usingDefaultLimit && totalCount !== undefined) {
|
|
430
|
+
response["truncated"] = buckets.length < totalCount;
|
|
431
|
+
response["totalCount"] = totalCount;
|
|
432
|
+
}
|
|
433
|
+
return response;
|
|
434
|
+
},
|
|
435
|
+
};
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* Distribution analysis with histogram
|
|
439
|
+
*/
|
|
440
|
+
export function createStatsDistributionTool(adapter) {
|
|
441
|
+
return {
|
|
442
|
+
name: "pg_stats_distribution",
|
|
443
|
+
description: "Analyze data distribution with histogram buckets, skewness, and kurtosis. Use groupBy to get distribution per category.",
|
|
444
|
+
group: "stats",
|
|
445
|
+
inputSchema: StatsDistributionSchemaBase, // Base schema for MCP visibility
|
|
446
|
+
annotations: readOnly("Distribution Analysis"),
|
|
447
|
+
icons: getToolIcons("stats", readOnly("Distribution Analysis")),
|
|
448
|
+
handler: async (params, _context) => {
|
|
449
|
+
const parsed = StatsDistributionSchema.parse(params);
|
|
450
|
+
const { table, column, buckets, schema, where, groupBy, groupLimit } = parsed;
|
|
451
|
+
const schemaName = schema ?? "public";
|
|
452
|
+
const schemaPrefix = schema ? `"${schema}".` : "";
|
|
453
|
+
const whereClause = where ? `WHERE ${where}` : "";
|
|
454
|
+
const numBuckets = buckets ?? 10;
|
|
455
|
+
// Validate column exists and is numeric
|
|
456
|
+
await validateNumericColumn(adapter, table, column, schemaName);
|
|
457
|
+
// Helper to compute skewness and kurtosis for a given group
|
|
458
|
+
const computeMoments = async (groupFilter) => {
|
|
459
|
+
const filterClause = groupFilter
|
|
460
|
+
? whereClause
|
|
461
|
+
? `${whereClause} AND ${groupFilter}`
|
|
462
|
+
: `WHERE ${groupFilter}`
|
|
463
|
+
: whereClause;
|
|
464
|
+
const statsQuery = `
|
|
465
|
+
WITH stats AS (
|
|
466
|
+
SELECT
|
|
467
|
+
MIN("${column}") as min_val,
|
|
468
|
+
MAX("${column}") as max_val,
|
|
469
|
+
AVG("${column}") as mean,
|
|
470
|
+
STDDEV_POP("${column}") as stddev,
|
|
471
|
+
COUNT("${column}") as n
|
|
472
|
+
FROM ${schemaPrefix}"${table}"
|
|
473
|
+
${filterClause}
|
|
474
|
+
),
|
|
475
|
+
moments AS (
|
|
476
|
+
SELECT
|
|
477
|
+
s.min_val,
|
|
478
|
+
s.max_val,
|
|
479
|
+
s.mean,
|
|
480
|
+
s.stddev,
|
|
481
|
+
s.n,
|
|
482
|
+
CASE WHEN s.stddev > 0 AND s.n > 2 THEN
|
|
483
|
+
(SUM(POWER(("${column}" - s.mean) / s.stddev, 3)) / s.n)::numeric(10,6)
|
|
484
|
+
ELSE NULL END as skewness,
|
|
485
|
+
CASE WHEN s.stddev > 0 AND s.n > 3 THEN
|
|
486
|
+
((SUM(POWER(("${column}" - s.mean) / s.stddev, 4)) / s.n) - 3)::numeric(10,6)
|
|
487
|
+
ELSE NULL END as kurtosis
|
|
488
|
+
FROM ${schemaPrefix}"${table}" t, stats s
|
|
489
|
+
${filterClause}
|
|
490
|
+
GROUP BY s.min_val, s.max_val, s.mean, s.stddev, s.n
|
|
491
|
+
)
|
|
492
|
+
SELECT * FROM moments
|
|
493
|
+
`;
|
|
494
|
+
const result = await adapter.executeQuery(statsQuery);
|
|
495
|
+
const row = result.rows?.[0];
|
|
496
|
+
if (row?.["min_val"] == null || row["max_val"] == null) {
|
|
497
|
+
return null;
|
|
498
|
+
}
|
|
499
|
+
return {
|
|
500
|
+
minVal: Number(row["min_val"]),
|
|
501
|
+
maxVal: Number(row["max_val"]),
|
|
502
|
+
skewness: row["skewness"] !== null ? Number(row["skewness"]) : null,
|
|
503
|
+
kurtosis: row["kurtosis"] !== null ? Number(row["kurtosis"]) : null,
|
|
504
|
+
};
|
|
505
|
+
};
|
|
506
|
+
// Helper to generate histogram for given min/max
|
|
507
|
+
const generateHistogram = async (minVal, maxVal, groupFilter) => {
|
|
508
|
+
const filterClause = groupFilter
|
|
509
|
+
? whereClause
|
|
510
|
+
? `${whereClause} AND ${groupFilter}`
|
|
511
|
+
: `WHERE ${groupFilter}`
|
|
512
|
+
: whereClause;
|
|
513
|
+
const histogramQuery = `
|
|
514
|
+
SELECT
|
|
515
|
+
WIDTH_BUCKET("${column}", ${String(minVal)}, ${String(maxVal + 0.0001)}, ${String(numBuckets)}) as bucket,
|
|
516
|
+
COUNT(*) as frequency,
|
|
517
|
+
MIN("${column}") as bucket_min,
|
|
518
|
+
MAX("${column}") as bucket_max
|
|
519
|
+
FROM ${schemaPrefix}"${table}"
|
|
520
|
+
${filterClause}
|
|
521
|
+
GROUP BY WIDTH_BUCKET("${column}", ${String(minVal)}, ${String(maxVal + 0.0001)}, ${String(numBuckets)})
|
|
522
|
+
ORDER BY bucket
|
|
523
|
+
`;
|
|
524
|
+
const result = await adapter.executeQuery(histogramQuery);
|
|
525
|
+
return (result.rows ?? []).map((row) => ({
|
|
526
|
+
bucket: Number(row["bucket"]),
|
|
527
|
+
frequency: Number(row["frequency"]),
|
|
528
|
+
rangeMin: Number(row["bucket_min"]),
|
|
529
|
+
rangeMax: Number(row["bucket_max"]),
|
|
530
|
+
}));
|
|
531
|
+
};
|
|
532
|
+
if (groupBy !== undefined) {
|
|
533
|
+
// Handle groupLimit: undefined uses default (20), 0 means no limit
|
|
534
|
+
const DEFAULT_GROUP_LIMIT = 20;
|
|
535
|
+
const userProvidedGroupLimit = groupLimit !== undefined;
|
|
536
|
+
const effectiveGroupLimit = groupLimit === 0 ? undefined : (groupLimit ?? DEFAULT_GROUP_LIMIT);
|
|
537
|
+
// Get distinct groups first
|
|
538
|
+
const groupsQuery = `
|
|
539
|
+
SELECT DISTINCT "${groupBy}" as group_key
|
|
540
|
+
FROM ${schemaPrefix}"${table}"
|
|
541
|
+
${whereClause}
|
|
542
|
+
ORDER BY "${groupBy}"
|
|
543
|
+
`;
|
|
544
|
+
const groupsResult = await adapter.executeQuery(groupsQuery);
|
|
545
|
+
const allGroupKeys = (groupsResult.rows ?? []).map((r) => r["group_key"]);
|
|
546
|
+
const totalGroupCount = allGroupKeys.length;
|
|
547
|
+
// Apply group limit
|
|
548
|
+
const groupKeys = effectiveGroupLimit !== undefined
|
|
549
|
+
? allGroupKeys.slice(0, effectiveGroupLimit)
|
|
550
|
+
: allGroupKeys;
|
|
551
|
+
// Process each group
|
|
552
|
+
const groups = [];
|
|
553
|
+
for (const groupKey of groupKeys) {
|
|
554
|
+
const groupFilter = typeof groupKey === "string"
|
|
555
|
+
? `"${groupBy}" = '${groupKey.replace(/'/g, "''")}'`
|
|
556
|
+
: `"${groupBy}" = ${String(groupKey)}`;
|
|
557
|
+
const moments = await computeMoments(groupFilter);
|
|
558
|
+
if (moments === null)
|
|
559
|
+
continue;
|
|
560
|
+
const { minVal, maxVal, skewness, kurtosis } = moments;
|
|
561
|
+
const bucketWidth = Math.round(((maxVal - minVal) / numBuckets) * 1e6) / 1e6;
|
|
562
|
+
const histogram = await generateHistogram(minVal, maxVal, groupFilter);
|
|
563
|
+
groups.push({
|
|
564
|
+
groupKey,
|
|
565
|
+
range: { min: minVal, max: maxVal },
|
|
566
|
+
bucketWidth,
|
|
567
|
+
skewness,
|
|
568
|
+
kurtosis,
|
|
569
|
+
histogram,
|
|
570
|
+
});
|
|
571
|
+
}
|
|
572
|
+
// Build response with truncation indicators
|
|
573
|
+
const response = {
|
|
574
|
+
table: `${schema ?? "public"}.${table}`,
|
|
575
|
+
column,
|
|
576
|
+
groupBy,
|
|
577
|
+
groups,
|
|
578
|
+
count: groups.length,
|
|
579
|
+
};
|
|
580
|
+
// Add truncation indicators when groups are limited
|
|
581
|
+
const groupsTruncated = effectiveGroupLimit !== undefined &&
|
|
582
|
+
totalGroupCount > effectiveGroupLimit;
|
|
583
|
+
if (groupsTruncated || !userProvidedGroupLimit) {
|
|
584
|
+
response["truncated"] = groupsTruncated;
|
|
585
|
+
response["totalGroupCount"] = totalGroupCount;
|
|
586
|
+
}
|
|
587
|
+
return response;
|
|
588
|
+
}
|
|
589
|
+
// Ungrouped distribution (existing logic)
|
|
590
|
+
const moments = await computeMoments();
|
|
591
|
+
if (moments === null) {
|
|
592
|
+
return { error: "No data or all nulls in column" };
|
|
593
|
+
}
|
|
594
|
+
const { minVal, maxVal, skewness, kurtosis } = moments;
|
|
595
|
+
const bucketWidth = Math.round(((maxVal - minVal) / numBuckets) * 1e6) / 1e6;
|
|
596
|
+
const histogram = await generateHistogram(minVal, maxVal);
|
|
597
|
+
return {
|
|
598
|
+
table: `${schema ?? "public"}.${table}`,
|
|
599
|
+
column,
|
|
600
|
+
range: { min: minVal, max: maxVal },
|
|
601
|
+
bucketWidth,
|
|
602
|
+
skewness,
|
|
603
|
+
kurtosis,
|
|
604
|
+
histogram,
|
|
605
|
+
};
|
|
606
|
+
},
|
|
607
|
+
};
|
|
608
|
+
}
|
|
609
|
+
/**
|
|
610
|
+
* Hypothesis testing (t-test or z-test)
|
|
611
|
+
*/
|
|
612
|
+
export function createStatsHypothesisTool(adapter) {
|
|
613
|
+
return {
|
|
614
|
+
name: "pg_stats_hypothesis",
|
|
615
|
+
description: "Perform one-sample t-test or z-test against a hypothesized mean. For z-test, provide populationStdDev (sigma) for accurate results. Use groupBy to test each group separately.",
|
|
616
|
+
group: "stats",
|
|
617
|
+
inputSchema: StatsHypothesisSchemaBase, // Base schema for MCP visibility
|
|
618
|
+
annotations: readOnly("Hypothesis Testing"),
|
|
619
|
+
icons: getToolIcons("stats", readOnly("Hypothesis Testing")),
|
|
620
|
+
handler: async (params, _context) => {
|
|
621
|
+
const { table, column, testType, hypothesizedMean, populationStdDev, schema, where, groupBy, } = StatsHypothesisSchema.parse(params);
|
|
622
|
+
const schemaName = schema ?? "public";
|
|
623
|
+
const schemaPrefix = schema ? `"${schema}".` : "";
|
|
624
|
+
const whereClause = where ? `WHERE ${where}` : "";
|
|
625
|
+
// Validate column exists and is numeric
|
|
626
|
+
await validateNumericColumn(adapter, table, column, schemaName);
|
|
627
|
+
// Helper to calculate test results from row stats
|
|
628
|
+
const calculateTestResults = (n, sampleMean, sampleStdDev) => {
|
|
629
|
+
if (n < 2 || isNaN(sampleStdDev) || sampleStdDev === 0) {
|
|
630
|
+
return { error: "Insufficient data or zero variance", sampleSize: n };
|
|
631
|
+
}
|
|
632
|
+
let stddevUsed;
|
|
633
|
+
let stddevNote;
|
|
634
|
+
if (testType === "z_test") {
|
|
635
|
+
if (populationStdDev !== undefined) {
|
|
636
|
+
stddevUsed = populationStdDev;
|
|
637
|
+
}
|
|
638
|
+
else {
|
|
639
|
+
stddevUsed = sampleStdDev;
|
|
640
|
+
stddevNote =
|
|
641
|
+
"No populationStdDev provided; using sample stddev (less accurate for z-test)";
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
else {
|
|
645
|
+
stddevUsed = sampleStdDev;
|
|
646
|
+
}
|
|
647
|
+
const standardError = stddevUsed / Math.sqrt(n);
|
|
648
|
+
const testStatistic = (sampleMean - hypothesizedMean) / standardError;
|
|
649
|
+
const degreesOfFreedom = n - 1;
|
|
650
|
+
// Calculate p-value based on test type
|
|
651
|
+
const pValue = testType === "z_test"
|
|
652
|
+
? calculateZTestPValue(testStatistic)
|
|
653
|
+
: calculateTTestPValue(testStatistic, degreesOfFreedom);
|
|
654
|
+
// Round p-value to 6 decimal places for cleaner output
|
|
655
|
+
const pValueRounded = Math.round(pValue * 1e6) / 1e6;
|
|
656
|
+
// Determine significance based on p-value
|
|
657
|
+
let interpretation;
|
|
658
|
+
if (pValueRounded < 0.001) {
|
|
659
|
+
interpretation =
|
|
660
|
+
"Highly significant (p < 0.001): Strong evidence against the null hypothesis";
|
|
661
|
+
}
|
|
662
|
+
else if (pValueRounded < 0.01) {
|
|
663
|
+
interpretation =
|
|
664
|
+
"Very significant (p < 0.01): Strong evidence against the null hypothesis";
|
|
665
|
+
}
|
|
666
|
+
else if (pValueRounded < 0.05) {
|
|
667
|
+
interpretation =
|
|
668
|
+
"Significant (p < 0.05): Evidence against the null hypothesis at α=0.05 level";
|
|
669
|
+
}
|
|
670
|
+
else if (pValueRounded < 0.1) {
|
|
671
|
+
interpretation =
|
|
672
|
+
"Marginally significant (p < 0.1): Weak evidence against the null hypothesis";
|
|
673
|
+
}
|
|
674
|
+
else {
|
|
675
|
+
interpretation =
|
|
676
|
+
"Not significant (p ≥ 0.1): Insufficient evidence to reject the null hypothesis";
|
|
677
|
+
}
|
|
678
|
+
// Build note with warnings
|
|
679
|
+
let noteText = stddevNote ??
|
|
680
|
+
"Two-tailed p-value calculated using numerical approximation";
|
|
681
|
+
if (n < 30) {
|
|
682
|
+
noteText =
|
|
683
|
+
`Small sample size (n=${String(n)}): results may be less reliable. ` +
|
|
684
|
+
noteText;
|
|
685
|
+
}
|
|
686
|
+
return {
|
|
687
|
+
sampleSize: n,
|
|
688
|
+
sampleMean,
|
|
689
|
+
sampleStdDev,
|
|
690
|
+
populationStdDev: testType === "z_test" ? (populationStdDev ?? null) : null,
|
|
691
|
+
standardError,
|
|
692
|
+
testStatistic,
|
|
693
|
+
pValue: pValueRounded,
|
|
694
|
+
degreesOfFreedom: testType === "t_test" ? degreesOfFreedom : null,
|
|
695
|
+
interpretation,
|
|
696
|
+
note: noteText,
|
|
697
|
+
};
|
|
698
|
+
};
|
|
699
|
+
if (groupBy !== undefined) {
|
|
700
|
+
// Grouped hypothesis tests
|
|
701
|
+
const sql = `
|
|
702
|
+
SELECT
|
|
703
|
+
"${groupBy}" as group_key,
|
|
704
|
+
COUNT("${column}") as n,
|
|
705
|
+
AVG("${column}")::numeric(20,6) as mean,
|
|
706
|
+
STDDEV_SAMP("${column}")::numeric(20,6) as stddev
|
|
707
|
+
FROM ${schemaPrefix}"${table}"
|
|
708
|
+
${whereClause}
|
|
709
|
+
GROUP BY "${groupBy}"
|
|
710
|
+
ORDER BY "${groupBy}"
|
|
711
|
+
`;
|
|
712
|
+
const result = await adapter.executeQuery(sql);
|
|
713
|
+
const rows = result.rows ?? [];
|
|
714
|
+
const groups = rows.map((row) => {
|
|
715
|
+
const n = Number(row["n"]);
|
|
716
|
+
const sampleMean = Number(row["mean"]);
|
|
717
|
+
const sampleStdDev = Number(row["stddev"]);
|
|
718
|
+
return {
|
|
719
|
+
groupKey: row["group_key"],
|
|
720
|
+
results: calculateTestResults(n, sampleMean, sampleStdDev),
|
|
721
|
+
};
|
|
722
|
+
});
|
|
723
|
+
return {
|
|
724
|
+
table: `${schema ?? "public"}.${table}`,
|
|
725
|
+
column,
|
|
726
|
+
testType,
|
|
727
|
+
hypothesizedMean,
|
|
728
|
+
groupBy,
|
|
729
|
+
groups,
|
|
730
|
+
count: groups.length,
|
|
731
|
+
};
|
|
732
|
+
}
|
|
733
|
+
// Ungrouped hypothesis test
|
|
734
|
+
const sql = `
|
|
735
|
+
SELECT
|
|
736
|
+
COUNT("${column}") as n,
|
|
737
|
+
AVG("${column}")::numeric(20,6) as mean,
|
|
738
|
+
STDDEV_SAMP("${column}")::numeric(20,6) as stddev
|
|
739
|
+
FROM ${schemaPrefix}"${table}"
|
|
740
|
+
${whereClause}
|
|
741
|
+
`;
|
|
742
|
+
const result = await adapter.executeQuery(sql);
|
|
743
|
+
const row = result.rows?.[0];
|
|
744
|
+
if (!row)
|
|
745
|
+
return { error: "No data found" };
|
|
746
|
+
const n = Number(row.n);
|
|
747
|
+
const sampleMean = Number(row.mean);
|
|
748
|
+
const sampleStdDev = Number(row.stddev);
|
|
749
|
+
const testResults = calculateTestResults(n, sampleMean, sampleStdDev);
|
|
750
|
+
// If error, return at top level (not nested in results)
|
|
751
|
+
if ("error" in testResults) {
|
|
752
|
+
return testResults;
|
|
753
|
+
}
|
|
754
|
+
return {
|
|
755
|
+
table: `${schema ?? "public"}.${table}`,
|
|
756
|
+
column,
|
|
757
|
+
testType,
|
|
758
|
+
hypothesizedMean,
|
|
759
|
+
results: testResults,
|
|
760
|
+
};
|
|
761
|
+
},
|
|
762
|
+
};
|
|
763
|
+
}
|
|
764
|
+
/**
|
|
765
|
+
* Random sampling
|
|
766
|
+
*/
|
|
767
|
+
export function createStatsSamplingTool(adapter) {
|
|
768
|
+
return {
|
|
769
|
+
name: "pg_stats_sampling",
|
|
770
|
+
description: "Get a random sample of rows. Use sampleSize for exact row count (any method), or percentage for approximate sampling with bernoulli/system methods.",
|
|
771
|
+
group: "stats",
|
|
772
|
+
inputSchema: StatsSamplingSchemaBase, // Base schema for MCP visibility
|
|
773
|
+
annotations: readOnly("Random Sampling"),
|
|
774
|
+
icons: getToolIcons("stats", readOnly("Random Sampling")),
|
|
775
|
+
handler: async (params, _context) => {
|
|
776
|
+
const { table, method, sampleSize, percentage, schema, select, where } = StatsSamplingSchema.parse(params);
|
|
777
|
+
const schemaName = schema ?? "public";
|
|
778
|
+
// Validate table exists
|
|
779
|
+
await validateTableExists(adapter, table, schemaName);
|
|
780
|
+
const schemaPrefix = schema ? `"${schema}".` : "";
|
|
781
|
+
const columns = select && select.length > 0
|
|
782
|
+
? select.map((c) => `"${c}"`).join(", ")
|
|
783
|
+
: "*";
|
|
784
|
+
const whereClause = where ? `WHERE ${where}` : "";
|
|
785
|
+
const samplingMethod = method ?? "random";
|
|
786
|
+
let sql;
|
|
787
|
+
let note;
|
|
788
|
+
// If sampleSize is provided, always use ORDER BY RANDOM() LIMIT n for exact counts
|
|
789
|
+
// TABLESAMPLE BERNOULLI/SYSTEM are percentage-based and cannot guarantee exact row counts
|
|
790
|
+
if (sampleSize !== undefined) {
|
|
791
|
+
const limit = sampleSize;
|
|
792
|
+
sql = `
|
|
793
|
+
SELECT ${columns}
|
|
794
|
+
FROM ${schemaPrefix}"${table}"
|
|
795
|
+
${whereClause}
|
|
796
|
+
ORDER BY RANDOM()
|
|
797
|
+
LIMIT ${String(limit)}
|
|
798
|
+
`;
|
|
799
|
+
if (percentage !== undefined) {
|
|
800
|
+
note = `sampleSize (${String(sampleSize)}) takes precedence over percentage (${String(percentage)}%). Using ORDER BY RANDOM() LIMIT for exact row count.`;
|
|
801
|
+
}
|
|
802
|
+
else if (samplingMethod !== "random") {
|
|
803
|
+
note = `Using ORDER BY RANDOM() LIMIT for exact ${String(sampleSize)} row count. TABLESAMPLE ${samplingMethod.toUpperCase()} is percentage-based and cannot guarantee exact counts.`;
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
else if (samplingMethod === "random") {
|
|
807
|
+
// Default random sampling with default limit (20 to reduce LLM context usage)
|
|
808
|
+
const limit = 20;
|
|
809
|
+
sql = `
|
|
810
|
+
SELECT ${columns}
|
|
811
|
+
FROM ${schemaPrefix}"${table}"
|
|
812
|
+
${whereClause}
|
|
813
|
+
ORDER BY RANDOM()
|
|
814
|
+
LIMIT ${String(limit)}
|
|
815
|
+
`;
|
|
816
|
+
if (percentage !== undefined) {
|
|
817
|
+
note = `percentage (${String(percentage)}%) is ignored for random method. Use method:'bernoulli' or method:'system' for percentage-based sampling, or use sampleSize for exact row count.`;
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
else {
|
|
821
|
+
// TABLESAMPLE with percentage (approximate row count)
|
|
822
|
+
// Apply default limit to prevent large payloads
|
|
823
|
+
const pct = percentage ?? 10;
|
|
824
|
+
const DEFAULT_TABLESAMPLE_LIMIT = 100;
|
|
825
|
+
sql = `
|
|
826
|
+
SELECT ${columns}
|
|
827
|
+
FROM ${schemaPrefix}"${table}"
|
|
828
|
+
TABLESAMPLE ${samplingMethod.toUpperCase()}(${String(pct)})
|
|
829
|
+
${whereClause}
|
|
830
|
+
LIMIT ${String(DEFAULT_TABLESAMPLE_LIMIT + 1)}
|
|
831
|
+
`;
|
|
832
|
+
// Add hint about system method unreliability for small tables
|
|
833
|
+
const methodHint = samplingMethod === "system"
|
|
834
|
+
? " Consider using 'bernoulli' or 'random' method for more reliable results on small tables."
|
|
835
|
+
: "";
|
|
836
|
+
note = `TABLESAMPLE ${samplingMethod.toUpperCase()}(${String(pct)}%) returns approximately ${String(pct)}% of rows. Actual count varies based on table size and sampling algorithm.${methodHint}`;
|
|
837
|
+
}
|
|
838
|
+
const result = await adapter.executeQuery(sql);
|
|
839
|
+
let rows = result.rows ?? [];
|
|
840
|
+
// Check if we need to truncate due to default limit for TABLESAMPLE methods
|
|
841
|
+
let truncated = false;
|
|
842
|
+
let totalSampled;
|
|
843
|
+
const DEFAULT_TABLESAMPLE_LIMIT = 100;
|
|
844
|
+
if (sampleSize === undefined &&
|
|
845
|
+
samplingMethod !== "random" &&
|
|
846
|
+
rows.length > DEFAULT_TABLESAMPLE_LIMIT) {
|
|
847
|
+
totalSampled = rows.length;
|
|
848
|
+
rows = rows.slice(0, DEFAULT_TABLESAMPLE_LIMIT);
|
|
849
|
+
truncated = true;
|
|
850
|
+
}
|
|
851
|
+
const response = {
|
|
852
|
+
table: `${schema ?? "public"}.${table}`,
|
|
853
|
+
method: samplingMethod,
|
|
854
|
+
sampleSize: rows.length,
|
|
855
|
+
rows,
|
|
856
|
+
};
|
|
857
|
+
// Add truncation indicators if applicable
|
|
858
|
+
if (truncated && totalSampled !== undefined) {
|
|
859
|
+
response.truncated = truncated;
|
|
860
|
+
response.totalSampled = totalSampled;
|
|
861
|
+
}
|
|
862
|
+
if (note !== undefined) {
|
|
863
|
+
response.note = note;
|
|
864
|
+
}
|
|
865
|
+
// Add note if requested sampleSize exceeded available rows
|
|
866
|
+
if (sampleSize !== undefined && rows.length < sampleSize) {
|
|
867
|
+
const existingNote = response.note !== undefined ? response.note + " " : "";
|
|
868
|
+
response.note =
|
|
869
|
+
existingNote +
|
|
870
|
+
`Requested ${String(sampleSize)} rows but only ${String(rows.length)} available.`;
|
|
871
|
+
}
|
|
872
|
+
return response;
|
|
873
|
+
},
|
|
874
|
+
};
|
|
875
|
+
}
|
|
876
|
+
//# sourceMappingURL=advanced.js.map
|