Debugging data, not just code: Using Claude and Cursor with Kuzu-MCP

Prashanth Rao
Prashanth Rao
AI Engineer at Kùzu Inc.
Chang Liu
Chang Liu
DevOps Engineer & Co-founder of Kùzu Inc.
Semih Salihoğlu
Semih Salihoğlu
CEO of Kùzu Inc. & Associate Prof. at UWaterloo

Unless you’ve been living under a rock, you’ve probably heard a lot about the Model Context Protocol (MCP), introduced by Anthropic in late 2024. We’re happy to announce that Kuzu now provides an MCP server that allows you to connect MCP clients — such as Claude Desktop and Cursor agents — to your Kuzu databases! This post has two goals. First, we’ll cover the basics of MCP and walk through how to connect your Kuzu databases to these two popular MCP clients using Kuzu’s MCP server. Second, we’ll demonstrate how debugging data issues can become a lot easier when you expose your database to an LLM through an MCP server. But first, let’s review MCP.

What is MCP?

MCP is an open protocol developed by Anthropic that standardizes how LLMs can interact with external data sources and services to obtain external data and/or take actions in the real world. MCP is a standardized client-server protocol where the client and server have the following roles:

  • Client is a “host application” that uses an LLM, such as Cursor or Claude Desktop. Client can read data from the server and/or make remote procedure calls to some functions exposed by the server. Through these function calls, an LLM can take actions in the real world when it is prompted to perform a task by a human.
  • Server is a tool or service that exposes external data and/or functions to the LLM.

Here is an example of how this architecture looks like with Kuzu MCP server in the role of the server. Kuzu MCP client-server overview

We’ll make this architecture very concrete in our demonstration scenario later in this post. For now, we just note that there is a proliferation of MCP servers (some are listed here). People are building different services that can be exposed to LLMs, each one giving more capabilities to LLMs to solve more complex and varied tasks automatically. You can point LLMs to fetch the latest stock and coin listings, to search nearby restaurants or help manage your Kubernetes cluster. Soon you may find yourself using an LLM to order your food, make doctor’s appointments1, or perform bank transactions (if you trust LLMs to do so)2.

Kuzu MCP Server

We’ve built an MCP server for Kuzu — let’s call it Kuzu-MCP in the rest of this post. Rather than starting the MCP server yourself, you configure Cursor or Claude Desktop clients to start the server.

Kuzu-MCP exposes the following two functions to LLMs:

FunctionDescription
getSchemaReturns the schema of the database
queryExecutes a Cypher query on the database

Using these functions, the LLM can read the node and relationship tables in Kuzu and run Cypher queries on the database to perform actions. In both Cursor and Claude Desktop, each time the LLM wants to run one of these functions, it asks your permission and you can choose to provide permission or not. If you are worried about the LLM accidentally modifying your database, you can also run Kuzu-MPC in read-only mode (see below), in which case, Kuzu-MCP will not run any queries that modify the database.

Demonstration scenario: A debugging session

Kuzu-MCP can be particularly useful to developers who want to use an LLM as an advanced programming assistant while developing Kuzu applications. In this post, we assume a scenario of a software developer who is using Kuzu as the database of an application and debugging a Cypher query that is not returning an expected result. The developer will delegate the job of debugging to the LLM, which will do its own debugging session until it finds the root cause of the problem.

A bug in a hierarchical financial asset database

Our example consists of a simple database of companies and the bonds they issue, where companies may be parents or subsidiaries of other companies. The schema of the database looks as follows:

  • Company(cID serial, name string, primary key (cid)) nodes.
  • Bond(bID serial, name string, yield float, primary key (bID)) nodes.
  • ParentOf(from Company, to Company) relationships, which form a hierarchy of companies.
  • Issues(from Company, to Bond) relationships, indicating which company issued which bonds.
Graph schema for the financial asset database

Next, suppose a developer is developing some analytics application on a dataset that consists of 3 companies: A, B,and C, where A is the parent of both B and C. Therefore, the developer expects that A is the root of the company hierarchy. Further, each company issues two bonds. So, there are 6 bonds in total in the database. Suppose the developer has a test case that checks that the number of total bonds is equal to the number of bonds issued by A or any of its direct or indirect subsidiaries. The test case is the following:

MATCH (a {name: "CompanyA"})-[e*]->(b:Bond)
WITH count(*) as bondsReachableByA 
MATCH (b:Bond) 
WITH bondsReachableByA, count(*) as allBonds
RETURN (bondsReachableByA = allBonds) as equal;

The result of the query must be true if A is the root of the company hierarchy, because the root company can reach every company in the database, and through them it can reach every bond in the database. For the purpose of demonstration, suppose the database has a bug and is missing the (A)-[:ParentOf]->(B) relationship. Therefore, the database actually looks as follows:

Graph visualization for the financial asset database

As a result of this bug, the developer observes that the test is failing. We’ll next show how to use Cursor along with Kuzu-MCP to debug this issue. We’ll assume in the rest of the post that the Kuzu database is in directory /path/to/your/local/financedb. If you want to replicate the rest of the steps in this post, use the Cypher queries here to create the buggy database above and just replace occurences of /path/to/your/local/financedb with your local directory.

Launch Cursor with Kuzu-MCP

Cursor is a popular IDE that supports MCP clients in its “Agent” mode. To connect to the Kuzu MCP server from Cursor, you need to do following:

  1. Install the Cursor app from cursor.com.
  2. Open the Cursor app and navigate to the “Cursor” menu on the top left corner.
  3. Click on “Settings > Cursor Settings” and then click on the “MCP” tab.
  4. Click on “Add new global MCP server”, which will open a new file called mcp.json.

To start Kuzu-MCP as Cursor starts, enter the following configuration into the mcp.json file:

{
    "mcpServers": {
        "kuzu": {
            "command": "docker",
            "args": [
                "run",
                "-v",
                "/path/to/your/local/financedb:/database",
                "-e",
                "KUZU_READ_ONLY=true",
                "--rm",
                "-i",
                "kuzudb/mcp-server"
            ]
        }
    }
}

Note that we set -e KUZU_READ_ONLY=true to run Kuzu-MCP in read-only mode, because in this session, we only want to use the LLM to read data from the database. Save the file, and restart the Cursor app.

Ask Cursor to debug the query

Perhaps the coolest part of this demo is how we run the debugging session with a very simple question to Cursor. We start a new chat in Cursor’s “Agent” mode and ask this simple question:

“From the kuzu database, I expect the result of the following query to be true. Why do I get false?”

MATCH (a {name: "CompanyA"})-[e*]->(b:Bond) 
WITH count(*) as bondsReachableByA 
MATCH (b:Bond) 
WITH bondsReachableByA, count(*) as allBonds
RETURN (bondsReachableByA = allBonds) as equal;

Note that we do not need to tell the LLM the name of the Kuzu database (this information is already in mcp.json). We’ll use Claude 3.7 Sonnet to debug this query.

Cursor debugging the query

After a few queries to the MCP server, the final result looks like this in Cursor: Cursor agents result using Kuzu-MCP

Let’s understand the sequence of events. Using the query function, the LLM (Claude 3.7 Sonnet, in this case) finds out that the reason the query returns false is that not all bonds in the database are reachable from CompanyA. Specifically, A does not have an edge to B and suggests that as the solution. Although we know we are at the phase where we are very used to being surprised by the things LLMs can do, it is still cool to see that it did the entire debugging session successfully, with an extremely simple prompt and only one prompt!

Notice also that its reasoning is quite sound and really mimics what a human would do in a debugging session. First, it looked at the database schema to understand the types of nodes and relationships. That’s the first time it’s seeing the database. Then it understood what the query is asking: “why are all bonds not reachable from CompanyA”. Then, it inspected which nodes are connected to which other nodes to find that the graph is disconnected and suggested to add an edge from A to B (or alternatively change the query). That’s how the human developer would approach this problem as well.

If you already use Cursor, you’ll know that it’s really good at debugging code, since it can see your entire code base. With MCP servers of databases, clients like Cursor can also help you debug problems in your data itself!

Use Kuzu-MCP in Claude Desktop

You can also use Kuzu-MCP with Claude Desktop, which is also completely able to go through a similar debugging session and get to the root cause of the problem. We won’t present the Claude Desktop interaction here but only show you how you can start Claude Desktop with Kuzu-MCP. The steps are as follows:

  1. Install the Claude Desktop app from claude.ai.
  2. Open the Claude Desktop app and navigate to the “Settings” tab.
  3. Click on the “Developer” tab and then on “Edit config”.
  4. This opens the directory containing the claude_desktop_config.json file.

Open the claude_desktop_config.json file in a text editor and copy-paste the following configuration into it. This is a Docker command that will start the Kuzu MCP server, and connect via a read-only connection to the Kuzu database on your local machine.

{
    "mcpServers": {
        "kuzu": {
            "command": "docker",
            "args": [
                "run",
                "-v",
                "/path/to/your/local/financedb:/database",
                "-e",
                "KUZU_READ_ONLY=true",
                "--rm",
                "-i",
                "kuzudb/mcp-server"
            ]
        }
    }
}

Save the file, and restart the Claude Desktop app. You should now be able to start querying the database via the MCP server.

Key takeaways

In this post we introduced the Kuzu MCP server and demonstrated how it can be useful when developing applications with Kuzu. We used a simple debugging session as an example. Since Kuzu-MCP allows LLMs to execute arbitrary Cypher queries on your database, you can even go beyond debugging — enabling agents to read from, modify, or even populate your database using nothing more than natural language prompts. This eliminates the need for long, detailed prompt engineering that includes schema or table dumps — the agent can access that context directly via MCP.

And this is just the beginning. By exposing multiple data systems through their own MCP servers, you can unlock powerful agentic workflows for tasks like ETL across databases, advanced analytics, or even automated data visualizations. We plan to cover more demonstrative examples in future posts.

We’d love to work with our developer community to learn about how they intend to use MCP servers and clients in their applications. Just like Kuzu itself, Kuzu-MCP is free and open source and available on GitHub. So, please try out our MCP server, share your thoughts on Discord, and check out our GitHub. Till next time!


Footnotes

  1. Speaking of doctor’s appointments: if you have read the initial vision paper of the semantic web articulated in the seminal paper by Tim Berners-Lee, James Hendler, and Ora Lassila, the proliferation of MCP servers should remind you of the imagined agentic application in the first paragraphs of that paper: an AI agent automatically talking to separate servers to make a doctor’s appointment for your mom. There are of course vast differences between how the semantic web paper imagines such agents and servers could work and how LLMs and MCP servers work. For example, the paper imagines the data exchanged between servers is RDF triples. Instead, LLMs exchange text, i.e., natural language, with servers (see footnote 2 below for more on this). Nonetheless, one can see a different form of the semantic web vision being realized in the proliferating MCP ecosystem. But let us leave this fascinating topic for another post.

  2. If you look at the 2nd page of the semantic web paper, there is a quote: “The Semantic Web will enable machines to COMPREHEND semantic documents and data, not human speech and writings.” This was hinting that semantic agents would understand ontologies and knowledge represented in RDF instead of text in web documents. In contrast to this vision, LLMs, which are modern day agents, comprehend human writings.