{
    "format": "getmcp/server-v1",
    "generator": {
        "product": "GetMCP",
        "version": "1.7.0"
    },
    "server": {
        "name": "Shop database",
        "slug": "shop-database",
        "status": "active",
        "transport_type": "streamable-http",
        "auth_type": "api-key",
        "auth_config": null,
        "outbound_auth_type": null,
        "outbound_auth_config": null,
        "cors_origins": null,
        "rate_limit_per_min": 60,
        "settings": {
            "description": "Explore your MySQL, MariaDB or PostgreSQL database with read-only queries.",
            "version": "1.0.0",
            "instructions": "Use these tools to answer questions about the user's database. Start with list_tables and describe_table, then use get_rows or run_query. Keep queries read-only and add a LIMIT. Explain what each query does in one line."
        }
    },
    "tools": [
        {
            "name": "list_tables",
            "slug": "list_tables",
            "description": "List the tables and views in the connected database, with an estimated row count and any comment for each. Start here when you do not know what the database contains, then use describe_table on the ones that look relevant. Row counts are estimates from the catalogue, not exact — use count_rows for an exact number.",
            "endpoint_url": "",
            "http_method": "POST",
            "tool_type": "database",
            "handler": "list_tables",
            "input_schema": {
                "type": "object",
                "properties": {
                    "include_views": {
                        "type": "boolean",
                        "description": "Include views as well as tables. Defaults to true."
                    }
                }
            },
            "body_template": null,
            "parameter_mapping": null,
            "response_mapping": null,
            "headers": null,
            "timeout": 30,
            "cache_ttl": 0,
            "retry_count": 0,
            "retry_backoff": "exponential",
            "ssl_verify": true,
            "rate_limit_per_min": 0,
            "status": "active",
            "tags": [],
            "annotations": {
                "readOnlyHint": true,
                "destructiveHint": false,
                "idempotentHint": true,
                "openWorldHint": true
            },
            "sort_order": 0
        },
        {
            "name": "describe_table",
            "slug": "describe_table",
            "description": "Show the structure of one table: every column with its type, nullability, default and comment, plus the primary key, indexes and foreign keys. Use it before writing a query against a table, so column names and types are right first time. Foreign keys tell you how tables join.",
            "endpoint_url": "",
            "http_method": "POST",
            "tool_type": "database",
            "handler": "describe_table",
            "input_schema": {
                "type": "object",
                "required": [
                    "table"
                ],
                "properties": {
                    "table": {
                        "type": "string",
                        "description": "Table name exactly as returned by list_tables — spaces, hyphens and capitals are fine, no quoting needed. A schema prefix (\"sales.orders\") is allowed."
                    }
                }
            },
            "body_template": null,
            "parameter_mapping": null,
            "response_mapping": null,
            "headers": null,
            "timeout": 30,
            "cache_ttl": 0,
            "retry_count": 0,
            "retry_backoff": "exponential",
            "ssl_verify": true,
            "rate_limit_per_min": 0,
            "status": "active",
            "tags": [],
            "annotations": {
                "readOnlyHint": true,
                "destructiveHint": false,
                "idempotentHint": true,
                "openWorldHint": true
            },
            "sort_order": 1
        },
        {
            "name": "run_query",
            "slug": "run_query",
            "description": "Run a read-only SQL statement — SELECT, WITH, SHOW, EXPLAIN or DESCRIBE — and return the rows. Use ? placeholders and pass the values in params rather than putting values into the SQL text. Runs inside a transaction the database holds read-only, so it cannot change data; use insert_row, update_rows, delete_rows or execute_sql for that. Results are capped: the response says whether rows were truncated, so add a LIMIT or narrow the WHERE when they were. One statement per call.",
            "endpoint_url": "",
            "http_method": "POST",
            "tool_type": "database",
            "handler": "run_query",
            "input_schema": {
                "type": "object",
                "required": [
                    "sql"
                ],
                "properties": {
                    "sql": {
                        "type": "string",
                        "description": "The statement to run, with ? for each value in params. Write it in the dialect of the connected engine (MySQL or PostgreSQL)."
                    },
                    "params": {
                        "type": "array",
                        "description": "Values for the ? placeholders, in order. Numbers, strings, booleans or null.",
                        "items": {
                            "type": [
                                "string",
                                "number",
                                "boolean",
                                "null"
                            ]
                        }
                    },
                    "limit": {
                        "type": "integer",
                        "description": "Maximum rows to return. Defaults to the connection's row cap and cannot exceed it; asking for more returns limit_clamped: true with the cap that applied.",
                        "minimum": 1
                    }
                }
            },
            "body_template": null,
            "parameter_mapping": null,
            "response_mapping": null,
            "headers": null,
            "timeout": 30,
            "cache_ttl": 0,
            "retry_count": 0,
            "retry_backoff": "exponential",
            "ssl_verify": true,
            "rate_limit_per_min": 0,
            "status": "active",
            "tags": [],
            "annotations": {
                "readOnlyHint": true,
                "destructiveHint": false,
                "idempotentHint": true,
                "openWorldHint": true
            },
            "sort_order": 2
        },
        {
            "name": "get_rows",
            "slug": "get_rows",
            "description": "Fetch rows from one table without writing SQL: pick columns, filter with simple conditions, sort, and page. Prefer this over run_query for straightforward lookups — it is safer and needs no dialect knowledge. The response carries has_more and next_offset for paging. For joins, aggregates or anything the filters cannot express, use run_query.",
            "endpoint_url": "",
            "http_method": "POST",
            "tool_type": "database",
            "handler": "get_rows",
            "input_schema": {
                "type": "object",
                "required": [
                    "table"
                ],
                "properties": {
                    "table": {
                        "type": "string",
                        "description": "Table name exactly as returned by list_tables — spaces, hyphens and capitals are fine, no quoting needed. A schema prefix (\"sales.orders\") is allowed."
                    },
                    "columns": {
                        "type": "array",
                        "description": "Columns to return. Omit for every column.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "where": {
                        "type": "object",
                        "description": "Filters, combined with AND. Each key is a column name exactly as describe_table returns it (spaces, hyphens and capitals are fine), optionally followed by an operator (=, !=, <, <=, >, >=, LIKE, NOT LIKE); each value is a plain value, a list (matched with IN) or null (matched with IS NULL). Example: {\"status\": \"paid\", \"total >=\": 100, \"Profile Visits >\": 50, \"deleted_at\": null, \"id\": [1, 2, 3]}.",
                        "additionalProperties": true
                    },
                    "order_by": {
                        "type": "string",
                        "description": "Column to sort by."
                    },
                    "order": {
                        "type": "string",
                        "description": "Sort direction when order_by is set. Defaults to asc.",
                        "enum": [
                            "asc",
                            "desc"
                        ]
                    },
                    "limit": {
                        "type": "integer",
                        "description": "Rows to return. Default 50. Cannot exceed the connection's row cap; asking for more returns limit_clamped: true with the cap that applied.",
                        "minimum": 1
                    },
                    "offset": {
                        "type": "integer",
                        "description": "Rows to skip, for paging. Pass next_offset from the previous response.",
                        "minimum": 0
                    }
                }
            },
            "body_template": null,
            "parameter_mapping": null,
            "response_mapping": null,
            "headers": null,
            "timeout": 30,
            "cache_ttl": 0,
            "retry_count": 0,
            "retry_backoff": "exponential",
            "ssl_verify": true,
            "rate_limit_per_min": 0,
            "status": "active",
            "tags": [],
            "annotations": {
                "readOnlyHint": true,
                "destructiveHint": false,
                "idempotentHint": true,
                "openWorldHint": true
            },
            "sort_order": 3
        },
        {
            "name": "count_rows",
            "slug": "count_rows",
            "description": "Count the rows in one table, optionally matching filters. Exact, unlike the estimates from list_tables. Use it to size a result before fetching it, or to answer \"how many\" questions directly.",
            "endpoint_url": "",
            "http_method": "POST",
            "tool_type": "database",
            "handler": "count_rows",
            "input_schema": {
                "type": "object",
                "required": [
                    "table"
                ],
                "properties": {
                    "table": {
                        "type": "string",
                        "description": "Table name exactly as returned by list_tables — spaces, hyphens and capitals are fine, no quoting needed. A schema prefix (\"sales.orders\") is allowed."
                    },
                    "where": {
                        "type": "object",
                        "description": "Filters, combined with AND. Each key is a column name exactly as describe_table returns it (spaces, hyphens and capitals are fine), optionally followed by an operator (=, !=, <, <=, >, >=, LIKE, NOT LIKE); each value is a plain value, a list (matched with IN) or null (matched with IS NULL). Example: {\"status\": \"paid\", \"total >=\": 100, \"Profile Visits >\": 50, \"deleted_at\": null, \"id\": [1, 2, 3]}.",
                        "additionalProperties": true
                    }
                }
            },
            "body_template": null,
            "parameter_mapping": null,
            "response_mapping": null,
            "headers": null,
            "timeout": 30,
            "cache_ttl": 0,
            "retry_count": 0,
            "retry_backoff": "exponential",
            "ssl_verify": true,
            "rate_limit_per_min": 0,
            "status": "active",
            "tags": [],
            "annotations": {
                "readOnlyHint": true,
                "destructiveHint": false,
                "idempotentHint": true,
                "openWorldHint": true
            },
            "sort_order": 4
        },
        {
            "name": "insert_row",
            "slug": "insert_row",
            "description": "Insert one row into a table from a column → value object. Use describe_table first so every required column is supplied with the right type. Returns the new auto-increment id on MySQL, or the inserted row on PostgreSQL. Refused while the connection is read-only. Confirm the data with the user before calling this.",
            "endpoint_url": "",
            "http_method": "POST",
            "tool_type": "database",
            "handler": "insert_row",
            "input_schema": {
                "type": "object",
                "required": [
                    "table",
                    "data"
                ],
                "properties": {
                    "table": {
                        "type": "string",
                        "description": "Table name exactly as returned by list_tables — spaces, hyphens and capitals are fine, no quoting needed. A schema prefix (\"sales.orders\") is allowed."
                    },
                    "data": {
                        "type": "object",
                        "description": "Column → value for the new row. Objects and lists are stored as JSON text.",
                        "additionalProperties": true
                    }
                }
            },
            "body_template": null,
            "parameter_mapping": null,
            "response_mapping": null,
            "headers": null,
            "timeout": 30,
            "cache_ttl": 0,
            "retry_count": 0,
            "retry_backoff": "exponential",
            "ssl_verify": true,
            "rate_limit_per_min": 0,
            "status": "inactive",
            "tags": [],
            "annotations": {
                "readOnlyHint": false,
                "destructiveHint": false,
                "idempotentHint": false,
                "openWorldHint": true
            },
            "sort_order": 5
        },
        {
            "name": "update_rows",
            "slug": "update_rows",
            "description": "Update the rows matching a filter, setting the columns in data. The filter is required and must not be empty — an update of every row is refused; use execute_sql if that is really what is wanted. Returns how many rows changed. Check the match with count_rows or get_rows first, and confirm with the user, because the change cannot be undone from here. Refused while the connection is read-only.",
            "endpoint_url": "",
            "http_method": "POST",
            "tool_type": "database",
            "handler": "update_rows",
            "input_schema": {
                "type": "object",
                "required": [
                    "table",
                    "data",
                    "where"
                ],
                "properties": {
                    "table": {
                        "type": "string",
                        "description": "Table name exactly as returned by list_tables — spaces, hyphens and capitals are fine, no quoting needed. A schema prefix (\"sales.orders\") is allowed."
                    },
                    "data": {
                        "type": "object",
                        "description": "Column → new value.",
                        "additionalProperties": true
                    },
                    "where": {
                        "type": "object",
                        "description": "Filters, combined with AND. Each key is a column name exactly as describe_table returns it (spaces, hyphens and capitals are fine), optionally followed by an operator (=, !=, <, <=, >, >=, LIKE, NOT LIKE); each value is a plain value, a list (matched with IN) or null (matched with IS NULL). Example: {\"status\": \"paid\", \"total >=\": 100, \"Profile Visits >\": 50, \"deleted_at\": null, \"id\": [1, 2, 3]}.",
                        "additionalProperties": true
                    }
                }
            },
            "body_template": null,
            "parameter_mapping": null,
            "response_mapping": null,
            "headers": null,
            "timeout": 30,
            "cache_ttl": 0,
            "retry_count": 0,
            "retry_backoff": "exponential",
            "ssl_verify": true,
            "rate_limit_per_min": 0,
            "status": "inactive",
            "tags": [],
            "annotations": {
                "readOnlyHint": false,
                "destructiveHint": false,
                "idempotentHint": true,
                "openWorldHint": true
            },
            "sort_order": 6
        },
        {
            "name": "delete_rows",
            "slug": "delete_rows",
            "description": "Delete the rows matching a filter. The filter is required and must not be empty — emptying a table is refused; use execute_sql if that is really what is wanted. Returns how many rows were deleted. Always check the match with count_rows or get_rows first and confirm with the user: deleted rows cannot be recovered from here. Refused while the connection is read-only.",
            "endpoint_url": "",
            "http_method": "POST",
            "tool_type": "database",
            "handler": "delete_rows",
            "input_schema": {
                "type": "object",
                "required": [
                    "table",
                    "where"
                ],
                "properties": {
                    "table": {
                        "type": "string",
                        "description": "Table name exactly as returned by list_tables — spaces, hyphens and capitals are fine, no quoting needed. A schema prefix (\"sales.orders\") is allowed."
                    },
                    "where": {
                        "type": "object",
                        "description": "Filters, combined with AND. Each key is a column name exactly as describe_table returns it (spaces, hyphens and capitals are fine), optionally followed by an operator (=, !=, <, <=, >, >=, LIKE, NOT LIKE); each value is a plain value, a list (matched with IN) or null (matched with IS NULL). Example: {\"status\": \"paid\", \"total >=\": 100, \"Profile Visits >\": 50, \"deleted_at\": null, \"id\": [1, 2, 3]}.",
                        "additionalProperties": true
                    }
                }
            },
            "body_template": null,
            "parameter_mapping": null,
            "response_mapping": null,
            "headers": null,
            "timeout": 30,
            "cache_ttl": 0,
            "retry_count": 0,
            "retry_backoff": "exponential",
            "ssl_verify": true,
            "rate_limit_per_min": 0,
            "status": "inactive",
            "tags": [],
            "annotations": {
                "readOnlyHint": false,
                "destructiveHint": true,
                "idempotentHint": true,
                "openWorldHint": true
            },
            "sort_order": 7
        },
        {
            "name": "execute_sql",
            "slug": "execute_sql",
            "description": "Run one SQL statement that changes data or structure — INSERT, UPDATE, DELETE, CREATE, ALTER, DROP and so on — with ? placeholders and values in params. Returns the number of rows affected and, on MySQL, the last insert id. This is the only tool that can change every row or alter tables, so show the user the exact statement and get their agreement before calling it. Refused while the connection is read-only. For reads use run_query, which is safer.",
            "endpoint_url": "",
            "http_method": "POST",
            "tool_type": "database",
            "handler": "execute_sql",
            "input_schema": {
                "type": "object",
                "required": [
                    "sql"
                ],
                "properties": {
                    "sql": {
                        "type": "string",
                        "description": "The statement to run, with ? for each value in params. One statement per call."
                    },
                    "params": {
                        "type": "array",
                        "description": "Values for the ? placeholders, in order.",
                        "items": {
                            "type": [
                                "string",
                                "number",
                                "boolean",
                                "null"
                            ]
                        }
                    }
                }
            },
            "body_template": null,
            "parameter_mapping": null,
            "response_mapping": null,
            "headers": null,
            "timeout": 30,
            "cache_ttl": 0,
            "retry_count": 0,
            "retry_backoff": "exponential",
            "ssl_verify": true,
            "rate_limit_per_min": 0,
            "status": "inactive",
            "tags": [],
            "annotations": {
                "readOnlyHint": false,
                "destructiveHint": true,
                "idempotentHint": false,
                "openWorldHint": true
            },
            "sort_order": 8
        }
    ],
    "resources": [],
    "prompts": [],
    "excluded": {
        "fields": [
            "auth_credentials",
            "outbound_auth_credentials",
            "test_auth_credentials"
        ],
        "reason": "Stored credentials are encrypted with a key unique to the site that saved them, so they cannot be restored elsewhere. Re-enter them after importing."
    }
}
