I tried operating TiDB Cloud Lake from Claude Code using MCP
This page has been translated by machine translation. View original
Hello, I'm sora from the Game Solutions Department.
This time, I'll write about connecting the TiDB Cloud Lake MCP server to Claude Code and using Claude Code to explore and manipulate data in Lake.
Conclusion First
- The connection information and command appear in the console's
Use with AI Tools, so it only takes one execution ofclaude mcp addto connect - When I asked Claude Code a question in Japanese, the AI constructed SQL to aggregate the results, and when it found something interesting, the AI itself issued additional queries to investigate the cause
- The MCP server has a safe mode, which is ON by default
- When safe mode is ON, even when connected as a user who can delete tables,
DROP TABLEwas blocked at the MCP server level - The scope of data visible to the AI and the operations it can perform could also be managed through permissions
GRANTed to the connected user
Checking Connection Information
TiDB Cloud Lake has an MCP server available, distributed via PyPI as tidbcloudlake-mcp.
Connection information can be checked from Use with AI Tools, which appears when you select a Warehouse from the Warehouse list in the console.

Under SQL User, a user called cloudapp appears.
This is a built-in SQL user that Lake creates from the start, and the MCP server connects to Lake using this username and password.
The password is masked, and if forgotten, you recreate it with Reset.
The data I'll be working with this time is appdb.app_logs (20,500 rows), modeled after application logs.
At the bottom of the screen, configuration examples for each client are listed.

There are tabs for Claude Code / Claude Desktop / Codex / Cursor / Gemini CLI / VS Code and others, and the Claude Code tab shows the claude mcp add command ready to use.
Registering with Claude Code
I run the command from the screen, changing only the database to appdb.
claude mcp add lake-mcp \
--env LAKE_DSN='lake://cloudapp:<password>@<tenant-id>.gw.aws-ap-northeast-1.default.lake.tidbcloud.com:443/appdb?warehouse=sora-blog-test' \
--env LAKE_MCP_SAFE_MODE=true \
-- uv tool run --from tidbcloudlake-mcp@latest lake-mcp
Added stdio MCP server lake-mcp with command: uv tool run --from tidbcloudlake-mcp@latest lake-mcp to local config
The official documentation assumes Python 3.12 or higher as a prerequisite, but if uv is installed, uv will fetch the necessary Python on first startup, so there was no need to prepare it separately.
LAKE_MCP_SAFE_MODE is the safe mode setting, and the default is true.
I'll verify what it does in the second half.
After restarting Claude Code and opening /mcp, lake-mcp was connected.
The list of available tools is listed in the official documentation mentioned earlier.
There are tools like show_databases / show_tables which return lists of databases and tables, describe_table which returns the schema, and execute_sql which executes SQL, and the AI combines these to explore Lake.
Note that LAKE_DSN including the password is stored in plain text in ~/.claude.json, and also appears as-is in the output of claude mcp get lake-mcp.
Care needs to be taken with screen sharing and handling of configuration files.
Asking Questions to Claude Code
From here, I'll ask questions to Claude Code in Japanese.
Claude Code calls MCP tools to send SQL to Lake and answers based on the returned results.
First, the list of databases.

Four databases were returned — appdb / default / information_schema / system — and it was explained that appdb is the user-created one.
The table list and schema can be retrieved in the same way.


In the schema description, it picked up not only the column types, but also that the actual column order is service, message, attributes, logged_at, log_id, level, and that all columns allow NULL.
I also tried asking for aggregation.

The AI constructed the SQL itself, and the executed SQL was also included in the response.
SELECT level, COUNT(*) AS cnt
FROM appdb.app_logs
GROUP BY level
ORDER BY cnt DESC;
When I asked "What time of day has the most errors?", the AI aggregated by time of day and then proactively investigated why only the 9 PM hour stood out.

The cause of the spike was 125 rows entered exactly at 2026-09-17 21:00:00, where all message values were in the form archive test row N.
These are test rows I inserted during a previous verification.
The AI determined these were test data, and answered that removing them shows no bias across time periods.
I only asked one sentence, but MCP tools were called 4 times.
I also asked why there were two similar tables.
In addition to app_logs, appdb has app_logs_cdc_raw (21,500 rows).
This is a staging table created when syncing with Lake's MySQL data source.

It determined from the row counts by add_time that the difference of 1,000 rows came from the same 500 rows (log_id 20001–20500) being ingested 3 times.
Furthermore, it even read my verification notes that were in the directory where Claude Code was launched, and confirmed the results matched.
It wasn't just using MCP tools — it combined them with Claude Code's built-in file search to investigate.
Verifying Safe Mode
cloudapp has the permissions to delete tables.
I'll ask the AI to delete using this user.
Safe Mode ON
The behavior when safe mode is ON is described in the official documentation as follows.
In safe mode: Read operations such as SELECT, SHOW, DESCRIBE, EXPLAIN, and LIST can access objects allowed by the configured TiDB Cloud Lake user. Write operations are limited to objects whose names start with the current mcp_sandbox_{session_id}_* prefix.
Reads are freely allowed within the scope of the connected user's permissions, and writes are only permitted to objects whose names begin with mcp_sandbox_<session_id>_.
When I asked to "delete the entire appdb.app_logs table in TiDB Cloud Lake", the AI tried to execute DROP TABLE after checking the contents, but was stopped.

Operation blocked: 'appdb' must start with mcp_sandbox_c151b811_
This is not a Lake permission error.
The MCP server examines the SQL before sending it to Lake and blocks writes to anything outside the sandbox.
The c151b811 part was a value that changed every time the MCP server was started.
The AI responded that "this guard is an intentional safety mechanism, and I will not attempt to bypass it from my side."
It then showed the method for the user to execute DROP TABLE directly from the console or similar, and the method of re-requesting after setting LAKE_MCP_SAFE_MODE=false, and the AI itself performed no further operations.
Safe Mode OFF
I re-registered with LAKE_MCP_SAFE_MODE=false and tried the same request.
claude mcp remove lake-mcp -s local
claude mcp add lake-mcp \
--env LAKE_DSN='lake://cloudapp:<password>@<tenant-id>.gw.aws-ap-northeast-1.default.lake.tidbcloud.com:443/appdb?warehouse=sora-blog-test' \
--env LAKE_MCP_SAFE_MODE=false \
-- uv tool run --from tidbcloudlake-mcp@latest lake-mcp

This time DROP TABLE appdb.app_logs was executed as-is, and the AI even checked the table list afterwards to confirm it was gone.
Checking the console also showed that app_logs had disappeared from appdb.

When a user with the necessary permissions turns off safe mode, there is nothing to stop the AI's operations.
Note that there is also a Session Sandbox Safety toggle in the Use with AI Tools screen, but this only switches whether LAKE_MCP_SAFE_MODE in the displayed command is true or false.
The settings of already-registered MCP servers don't change, so use claude mcp get lake-mcp to check which mode is currently active.
Recovery with UNDROP TABLE
A deleted table can be restored with UNDROP TABLE within the Time Travel retention period.
The retention period is 24 hours by default.
Execute it in a Worksheet.
UNDROP TABLE appdb.app_logs;

app_logs was restored with 20,500 rows, and the Creation Time was also unchanged from the original.
Verifying with a User with Restricted Permissions
The official documentation states that the MCP server accesses data with the permissions of the connected user.
The MCP server can access data with the permissions of the configured TiDB Cloud Lake user.
So I'll try connecting with a user that has restricted permissions instead of cloudapp.
I'll leave safe mode OFF and see if it's stopped by the user's permissions alone.
User Without a Role
Users can also be added from Admin in the console, but the options there are members of the TiDB Cloud organization, with only two roles: account_admin and public.
These users log in with their TiDB Cloud credentials and don't have passwords, so they can't be used in MCP's LAKE_DSN.
For MCP use, I'll create a SQL user via a Worksheet.
Without specifying a role, the user is only assigned the built-in public role.
public is a role with no permissions.
CREATE USER mcp_public IDENTIFIED BY '<password>';
Incidentally, after execution, checking Monitoring > SQL History showed the IDENTIFIED BY '<password>' part displayed as-is.
Since anyone who can see SQL History can also see the password, in a shared environment you would need to consider changing the password after creation.
When I connected with this user and asked for the database list, only information_schema and system were returned.

The AI answered "There are no databases I've created yet."
appdb simply isn't visible due to lack of permissions, but since only the visible range is returned without an error, it appears to the AI as "non-existent."
Whether something is visible is determined by permissions, not who created it — when I changed the console account to account_admin, appdb created by another user was also visible.
When I asked for the row count, this time it resulted in a permission error.
Permission denied: privilege [Select] is required on 'default'.'appdb'.'app_logs' for user 'mcp_public'@'%' with roles [public]
With only public, even reading is not possible, so the user passed to the AI needs at least SELECT.
Granting a Read-Only Role
I'll create a role with only SELECT on appdb and assign it to mcp_public.
CREATE ROLE mcp_readonly_role;
GRANT SELECT ON appdb.* TO ROLE mcp_readonly_role;
GRANT ROLE mcp_readonly_role TO mcp_public;
ALTER USER mcp_public WITH DEFAULT_ROLE = 'mcp_readonly_role';
With only GRANT ROLE, the role at login remains public.
I'm also switching DEFAULT_ROLE with ALTER USER.

After restarting Claude Code, appdb was now visible and row counts could be retrieved.

When I asked for deletion in the same way, the AI asked whether I meant DROP TABLE or DELETE, so I replied to drop the entire table.

Permission denied: privilege [Drop] is required on 'default'.'appdb'.'app_logs' for user 'mcp_public'@'%' with roles [mcp_readonly_role,public]
Safe mode is OFF, but this time it was stopped by Lake's permissions, and the table remained.
This is the expected behavior for GRANT. However, I felt that this result most clearly demonstrates that the permissions of the user passed to the AI directly become what the AI is capable of doing.
Handling of cloudapp
Even when logging into the console with a public role account and opening Use with AI Tools, the SQL User was still the same cloudapp.
cloudapp is a single user shared by everyone using the console.
Reset shows "Only administrators can reset the DB password" and cannot be pressed, but if someone is given the password, they can connect with cloudapp's permissions.
The console-side role has no relation to MCP connections.
Pressing the ? next to SQL User says it can be disabled if not needed.
ALTER USER cloudapp WITH DISABLED = true;
If you create individual users for MCP, you can adopt a practice of disabling the shared cloudapp.
Closing
This time, I connected the TiDB Cloud Lake MCP server to Claude Code and tried exploring and manipulating Lake data from Claude Code.
Connecting required just one command, and while the AI constructs SQL and investigates on its own, a table was actually deleted when using a privileged user with safe mode OFF — so I felt it's best to restrict the permissions of the user passed to the AI from the start.
I hope this article is helpful to someone.