Skip to main content

MCP server

Overview​

The MCP server lets AI agents browse and manage Gravitino metadata through the Model Context Protocol. Agents call tools such as get_list_of_catalogs or get_table_metadata_details, and the server turns each call into a request to the Gravitino server on behalf of the agent's user, so Gravitino authorizes every call exactly as it would the same request from the UI or the API.

The Helm chart installs the MCP server alongside the Gravitino server by default, and the ingress from Install with Helm publishes it at /mcp on the UI hostname.

Quick start​

The commands use the shell variables set in step 1 of Install with Helm.

  1. Check that the server is running. The MCP pod starts after the Gravitino server answers, so it can sit in its init container for a minute after an install.

    Check the MCP pod
    kubectl -n "$NAMESPACE" get pods | grep mcp

    The pod should show Running with all containers ready.

  2. Point the agent at the endpoint. The address is https://{ui_hostname}/mcp. Each request carries the agent user's own credentials, which with the chart's default basic authenticator are a user name and password in a Basic header. Taking Cursor as an example:

    ~/.cursor/mcp.json
    {
    "mcpServers": {
    "gravitino": {
    "url": "https://{ui_hostname}/mcp",
    "headers": {
    "Authorization": "Basic {base64_user_password}"
    }
    }
    }
    }

    Produce the header value with printf '%s' '{user}:{password}' | base64. Other agents take the same URL and header in their own configuration format.

  3. Ask for something the user can see. A request such as "list the catalogs in metalake {metalake}" should return the catalogs that user is entitled to. A user with no access to the metalake gets an authorization error back from Gravitino.

Configuration​

The MCP server is configured through the mcp block of my-values.yaml. The common settings:

SettingDescriptionDefault
mcp.enabledDeploy the MCP servertrue
mcp.metalakeMetalake used when a tool call does not name one. Leave empty to have agents name the metalake on every call(none)
mcp.gravitinoUriGravitino server the MCP server calls. Leave empty to use the Gravitino server in the same release(same release)
mcp.extraArgsAdditional server arguments, for example ["--tag", "table"] to expose only the tools tagged table[]
mcp.auth.token, mcp.auth.existingSecretStatic Bearer token used for requests that carry no Authorization header. See Authentication(none)
mcp.auth.oauth.*OAuth client credentials for a service identity that fetches and refreshes its own token(none)
mcp.auth.oauth.noServiceIdentityFallbackReject requests that carry no Authorization header instead of using the service identityfalse
mcp.tls.enabled, mcp.tls.existingSecretServe HTTPS from the pod itself, from a kubernetes.io/tls Secret. Not needed when the ingress terminates TLSfalse
mcp.replicaCountNumber of replicas. The server keeps no state, so replicas scale freely1
mcp.extraVolumes, mcp.extraVolumeMountsAdditional volumes, for example to keep the audit log across restarts. See Audit Logging[]

Publish the endpoint through the top-level ingress, as Install with Helm does, rather than enabling the chart's separate mcp.ingress.

Authentication​

Per-request identity​

Every incoming request's Authorization header is forwarded to Gravitino unchanged, so each agent acts as its own user and Gravitino authorizes each call for that user. Concurrent sessions from different users stay isolated, and one user's identity never reaches another's calls. Send Basic credentials under the basic authenticator, or a Bearer token from your identity provider under oauth. Leave the mcp.auth settings empty to require this for every request.

Service identity​

A request that arrives without an Authorization header falls back to a service identity when one is configured, and every such request then acts as that one identity. Two settings provide it:

  • A static token, in mcp.auth.token or in the Secret named by mcp.auth.existingSecret. The value is always sent as a Bearer token, so it must be an OAuth access token, and it stops working when that token expires.
  • OAuth client credentials, in mcp.auth.oauth.tokenEndpoint, clientId, and clientSecret (or existingSecret), which must be set together. The server fetches its own token and refreshes it, so a long-running server does not start failing when a token expires.

A static token wins when both are set. Set mcp.auth.oauth.noServiceIdentityFallback to true to keep the client credentials while still rejecting requests that carry no identity of their own.

Authorization is always decided by Gravitino. The MCP server forwards the identity and makes no access-control decisions of its own.

Supported tools​

Every tool carries a tag, and --tag in mcp.extraArgs limits the server to the tools with that tag.

Tool nameDescriptionTag
get_list_of_catalogsRetrieve a list of all catalogs in the system.catalog
create_catalogCreate a new catalog.catalog
alter_catalogAlter an existing catalog.catalog
drop_catalogDrop a catalog.catalog
set_catalog_in_useEnable or disable a catalog.catalog
get_list_of_schemasRetrieve a list of schemas belonging to a specific catalog.schema
create_schemaCreate a new schema.schema
alter_schemaAlter an existing schema.schema
drop_schemaDrop a schema.schema
get_list_of_tablesRetrieve a list of tables within a specific catalog and schema.table
get_table_metadata_detailsRetrieve comprehensive metadata details for a specific table.table
create_tableCreate a new table.table
alter_tableAlter an existing table.table
drop_tableDrop a table.table
list_of_modelsRetrieve a list of models within a specific catalog and schema.model
load_modelRetrieve comprehensive metadata details for a specific model.model
list_model_versionsRetrieve a list of versions for a specific model.model
load_model_versionRetrieve comprehensive metadata details for a specific model version.model
load_model_version_by_aliasRetrieve comprehensive metadata details for a specific model version by alias.model
register_modelRegister a new model.model
delete_modelDelete a model.model
link_model_versionLink a new version to a model.model
delete_model_versionDelete a model version.model
delete_model_version_by_aliasDelete a model version by one of its aliases.model
alter_modelAlter an existing model.model
alter_model_versionAlter a model version.model
alter_model_version_by_aliasAlter a model version by one of its aliases.model
metadata_type_to_fullname_formatsRetrieve the metadata type to fullname formats mapping.metadata
list_of_topicsRetrieve a list of topics within a specific catalog and schema.topic
load_topicRetrieve comprehensive metadata details for a specific topic.topic
create_topicCreate a new topic.topic
alter_topicAlter an existing topic.topic
delete_topicDelete a topic.topic
list_of_filesetsRetrieve a list of filesets within a specific catalog and schema.fileset
load_filesetRetrieve comprehensive metadata details for a specific fileset.fileset
list_files_in_filesetRetrieve a list of files within a specific fileset.fileset
create_filesetCreate a new fileset.fileset
alter_filesetAlter an existing fileset.fileset
drop_filesetDrop a fileset.fileset
list_of_jobsRetrieve a list of jobsjob
get_job_by_idRetrieve a job by its ID.job
list_of_job_templatesRetrieve a list of job templates.job
get_job_template_by_nameRetrieve a job template by its name.job
run_jobRun a job with the specified parameters.job
cancel_jobCancel a running job by its ID.job
get_tag_by_nameRetrieve a tag by its name.tag
list_of_tagsRetrieve a list of tags.tag
list_tags_for_metadataRetrieve a list of tags associated with a specific metadata item.tag
list_metadata_by_tagRetrieve a list of metadata items associated with a specific tag.tag
associate_tag_with_metadataAssociate tags with a specific metadata item.tag
disassociate_tag_from_metadataDisassociate tags from a specific metadata item.tag
create_tagCreate a new tag.tag
alter_tagAlter an existing tag.tag
delete_tagDelete a tag.tag
list_statistics_for_metadataRetrieve a list of statistics associated with a specific metadata item.statistics
list_statistics_for_partitionRetrieve a list of statistics associated with a specific partition.statistics
get_list_of_policiesRetrieve a list of policies in the system.policy
get_policy_detail_informationRetrieve detailed information for a specific policy by policy name.policy
list_policies_for_metadataList all policies associated with a specific metadata item.policy
list_metadata_by_policyList all metadata items associated with a specific policy.policy
get_policy_for_metadataGet a policy associated with a specific metadata item.policy
list_of_partitionsRetrieve partitions for a table. Only for catalogs with a partition API.partition
get_partitionRetrieve a partition's metadata. Only for catalogs with a partition API.partition
list_of_viewsRetrieve a list of views for a schema. Only for catalogs supporting views.view
load_viewRetrieve a view's metadata. Only for catalogs supporting views.view

Audit logging​

Every tool call is recorded as one JSON line in gravitino-mcp-audit.log, attributed to the user derived from the request's Authorization header.

FieldDescription
timestampUTC ISO-8601 time of the call.
principalCaller identity: user name for Basic credentials, bearer:{first_8_chars} for a Bearer token, or anonymous when no identity is present.
toolName of the invoked MCP tool.
outcomeallow for successful calls, deny for failed ones. deny is emitted for any tool-call exception (authorization denial being the common case); inspect error_type to disambiguate.
error_typeException class name, present only when outcome is deny.
Example audit record
{"timestamp": "2026-06-16T03:21:09.123456+00:00", "principal": "alice", "tool": "get_list_of_catalogs", "outcome": "allow"}

The log is written to the container's working directory and is lost when the pod restarts. To keep it, mount a volume at the working directory with mcp.extraVolumes and mcp.extraVolumeMounts, or collect it from the pod with your log collector.