MCP Server for Agents
View as MarkdownTo enable this feature in your Materialize region, contact our team.
Materialize provides a built-in Model Context Protocol (MCP) endpoint that lets AI agents discover and query your real-time data products over HTTP. The MCP interface is served directly by the database; no sidecar process or external server is required.
Endpoint: POST /api/mcp/agents (HTTP port, default 6876)
The endpoint uses JSON-RPC 2.0 over
HTTP POST and supports the MCP initialize, tools/list, and tools/call
methods.
Connect to the MCP server
Step 1. Get your credentials
You need your email address (or service account name) and an app password.
To create an app password:
- Log in to the Materialize Console.
- Go to Account > App Passwords > New app password.
- Copy the generated password — you won’t be able to see it again.
Step 2. Encode your credentials in Base64
MCP clients send credentials as a Base64-encoded user:password string. Run
this in your terminal:
printf '<user>:<app_password>' | base64
For example:
printf 'svc-mcp-agent@mycompany.com:my_app_password_here' | base64
# Output: c3ZjLW1jcC1hZ2VudEBteWNvbXBhbnkuY29tOm15X2FwcF9wYXNzd29yZF9oZXJl
Step 3. Get your hostname
Find your region hostname in the Materialize Console under Connect. It looks like:
<region-id>.materialize.cloud
Your full MCP endpoint URL is:
https://<region-id>.materialize.cloud/api/mcp/agents
Use your Materialize host and the HTTP port (default 6876):
http://<host>:6876/api/mcp/agents
Step 4. Configure your MCP client
Create a .mcp.json file in your project directory:
{
"mcpServers": {
"materialize-agents": {
"type": "http",
"url": "https://<region-id>.materialize.cloud/api/mcp/agents",
"headers": {
"Authorization": "Basic <base64-token>"
}
}
}
}
Add to your Claude Desktop MCP configuration (claude_desktop_config.json):
{
"mcpServers": {
"materialize-agents": {
"url": "https://<region-id>.materialize.cloud/api/mcp/agents",
"headers": {
"Authorization": "Basic <base64-token>"
}
}
}
}
In Cursor’s MCP settings (.cursor/mcp.json):
{
"mcpServers": {
"materialize-agents": {
"url": "https://<region-id>.materialize.cloud/api/mcp/agents",
"headers": {
"Authorization": "Basic <base64-token>"
}
}
}
}
Any MCP-compatible client can connect by sending JSON-RPC 2.0 requests:
curl -X POST https://<region-id>.materialize.cloud/api/mcp/agents \
-H "Content-Type: application/json" \
-H "Authorization: "Basic <base64-token>"" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list"
}'
Enabling the endpoint
The agents endpoint is disabled by default. Enable it at runtime using system parameters:
| Parameter | Default | Description |
|---|---|---|
enable_mcp_agents |
false |
Enable or disable the /api/mcp/agents endpoint. |
enable_mcp_agents_query_tool |
false |
Show or hide the query tool on the agents endpoint. |
mcp_max_response_size |
1000000 |
Maximum response size in bytes. Queries exceeding this limit return an error. |
ALTER SYSTEM SET enable_mcp_agents = true;
When the endpoint is disabled, requests return HTTP 503 (Service Unavailable).
Authentication and access control
Accessing the MCP endpoint requires basic authentication,
just as connecting via a SQL client (e.g. psql). The authenticated role
determines which data products are visible based on RBAC privileges.
Use the credentials of a Materialize user or service account:
- User ID: Your email address or service account name.
- Password: An app password.
For production use, we recommend creating a dedicated service account and granting it a role with limited privileges (see Required privileges).
Create a functional role for MCP privileges, then assign it to a login role:
CREATE ROLE mcp_agent;
CREATE ROLE my_agent LOGIN PASSWORD 'secret';
GRANT mcp_agent TO my_agent;
Authenticate using the login role credentials (my_agent). You can create
additional login roles and grant them the same mcp_agent role as needed.
Define and document data products for your agents
The MCP server allows agents to discover and query documented data products. In Materialize, you can make a data product discoverable to agents by creating a materialized view, adding a comment, and optionally adding an index for faster lookups. A comment is required, so agents understand the purpose of each data product.
1. Create a dedicated cluster and schema
Use a dedicated cluster and schema to isolate agent workloads. This ensures agent queries do not consume resources from your other clusters, and limits visibility to only the data products you choose to expose.
CREATE CLUSTER mcp_cluster SIZE '25cc';
CREATE SCHEMA mcp_schema;
2. Create and index a view
Create a materialized view in the dedicated schema. We recommend installing an index on the dedicated cluster for faster lookups. Every indexed column becomes a required input parameter in the tool’s schema.
SET cluster = mcp_cluster;
CREATE MATERIALIZED VIEW mcp_schema.payment_status AS
SELECT order_id, user_id, status, updated_at
FROM orders
JOIN payments USING (order_id);
CREATE INDEX payment_status_order_id_idx ON mcp_schema.payment_status (order_id);
3. Add a comment
The comment on the index becomes the data product’s description. Column comments on the underlying view become parameter descriptions. Write comments that help a language model understand when and how to use the tool.
COMMENT ON INDEX mcp_schema.payment_status_order_id_idx IS
'Given an order ID, return the current payment status and last update time.
Use this tool to drive user-facing payment tracking.';
COMMENT ON COLUMN mcp_schema.payment_status.order_id IS
'The unique identifier for the order';
4. Verify your data products
To confirm which data products are visible to your agent role, run:
SET ROLE mcp_agent;
SELECT * FROM mz_internal.mz_mcp_data_products;
If a data product is missing, check that:
- The view has an index with a comment.
- The role has
USAGEon the database, schema, and cluster. - The role has
SELECTon the view.
Required privileges
The role used to authenticate with the MCP endpoint must have:
USAGEon the database and schema containing the view.SELECTon the view.USAGEon the cluster where the index is installed.
Lock the role to the dedicated cluster and schema so that all agent queries are isolated.
On Cloud, create a functional role and grant it to a service account. The service account’s app password is used for MCP authentication.
CREATE ROLE mcp_agent;
GRANT USAGE ON DATABASE materialize TO mcp_agent;
GRANT USAGE ON SCHEMA mcp_schema TO mcp_agent;
GRANT SELECT ON ALL TABLES IN SCHEMA mcp_schema TO mcp_agent;
GRANT USAGE ON CLUSTER mcp_cluster TO mcp_agent;
-- Lock the role to the dedicated cluster and schema.
-- This ensures all queries from this role run on mcp_cluster
-- and only see objects in mcp_schema by default.
ALTER ROLE mcp_agent SET cluster TO mcp_cluster;
ALTER ROLE mcp_agent SET search_path TO mcp_schema;
-- Grant the role to your service account
GRANT mcp_agent TO '<service-account-name>';
Create a functional role for privileges, then assign it to a login role:
-- Functional role (cannot log in, holds privileges)
CREATE ROLE mcp_agent;
GRANT USAGE ON DATABASE materialize TO mcp_agent;
GRANT USAGE ON SCHEMA mcp_schema TO mcp_agent;
GRANT SELECT ON ALL TABLES IN SCHEMA mcp_schema TO mcp_agent;
GRANT USAGE ON CLUSTER mcp_cluster TO mcp_agent;
-- Lock the role to the dedicated cluster and schema.
-- This ensures all queries from this role run on mcp_cluster
-- and only see objects in mcp_schema by default.
ALTER ROLE mcp_agent SET cluster TO mcp_cluster;
ALTER ROLE mcp_agent SET search_path TO mcp_schema;
-- Login role (used for authentication)
CREATE ROLE my_agent LOGIN PASSWORD 'secret';
GRANT mcp_agent TO my_agent;
You can create additional login roles and grant them the same mcp_agent role
as needed.
If any privilege is missing, the data product will not appear in the agent’s tool list.
Tools
get_data_products
Discover all available data products. Returns a lightweight list with name, cluster, and description for each product.
Parameters: None.
Example response:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [
{
"type": "text",
"text": "[\n [\n \"\\\"materialize\\\".\\\"mcp_schema\\\".\\\"payment_status\\\"\",\n \"mcp_cluster\",\n \"Given an order ID, return the current payment status.\"\n ]\n]"
}
],
"isError": false
}
}
get_data_product_details
Get the full details for a specific data product, including its JSON schema with column names, types, and descriptions.
| Parameter | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Exact name from the get_data_products list. |
Example response:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [
{
"type": "text",
"text": "[\n [\n \"\\\"materialize\\\".\\\"mcp_schema\\\".\\\"payment_status\\\"\",\n \"mcp_cluster\",\n \"Given an order ID, return the current payment status.\",\n \"{\\\"order_id\\\": {\\\"type\\\": \\\"integer\\\", \\\"position\\\": 1}, \\\"status\\\": {\\\"type\\\": \\\"text\\\", \\\"position\\\": 3}}\"\n ]\n]"
}
],
"isError": false
}
}
read_data_product
Read rows from a data product.
| Parameter | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Fully-qualified name, e.g. "materialize"."public"."payment_status". |
limit |
integer | No | Maximum rows to return. Default: 500, max: 1000. |
cluster |
string | No | Cluster override. If omitted, uses the cluster from the catalog. |
Example response:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [
{
"type": "text",
"text": "[\n [\n 1001,\n 42,\n \"shipped\",\n \"2026-03-26T10:30:00Z\"\n ]\n]"
}
],
"isError": false
}
}
query
query tool is disabled by default. To enable it, set the
enable_mcp_agents_query_tool system parameter to true.
Execute a SQL SELECT statement against your data products.
| Parameter | Type | Required | Description |
|---|---|---|---|
cluster |
string | Yes | Exact cluster name from the data product details. |
sql_query |
string | Yes | PostgreSQL-compatible SELECT statement. |
Example response:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [
{
"type": "text",
"text": "[\n [\n 42,\n \"shipped\"\n ]\n]"
}
],
"isError": false
}
}