This is an automated email from the ASF dual-hosted git repository.
jshao pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gravitino.git
The following commit(s) were added to refs/heads/main by this push:
new 1f0ae44905 [#8112] feat(mcp): Support Gravitino MCP server docker
image (#8139)
1f0ae44905 is described below
commit 1f0ae44905de886c5bfacc1adbbc4ab3bbc186b2
Author: FANNG <[email protected]>
AuthorDate: Wed Aug 27 18:21:13 2025 +0900
[#8112] feat(mcp): Support Gravitino MCP server docker image (#8139)
### What changes were proposed in this pull request?
Add docker support for MCP server
### Why are the changes needed?
Fix: #8112
### Does this PR introduce _any_ user-facing change?
no
### How was this patch tested?
build local docker image and test with Cursor
---
.github/workflows/docker-image.yml | 4 +++
dev/docker/build-docker.sh | 4 ++-
dev/docker/mcp-server/Dockerfile | 37 ++++++++++++++++++++++++++
dev/docker/mcp-server/mcp-server-dependency.sh | 32 ++++++++++++++++++++++
dev/docker/mcp-server/start-mcp-server.sh | 23 ++++++++++++++++
docs/docker-image-details.md | 16 +++++++++++
docs/gravitino-mcp-server.md | 4 +++
docs/index.md | 6 +++++
8 files changed, 125 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/docker-image.yml
b/.github/workflows/docker-image.yml
index 4bd63eed73..ab841315df 100644
--- a/.github/workflows/docker-image.yml
+++ b/.github/workflows/docker-image.yml
@@ -19,6 +19,7 @@ on:
- 'gravitino-playground:hive'
- 'gravitino-playground:ranger'
- 'gravitino-iceberg-rest-server'
+ - 'gravitino-mcp-server'
docker_repo_name:
description: 'Docker repository name (default is apache)'
required: false
@@ -91,6 +92,9 @@ jobs:
elif [ "${{ github.event.inputs.image }}" ==
"gravitino-iceberg-rest-server" ]; then
echo "image_type=iceberg-rest-server" >> $GITHUB_ENV
echo "image_name=${{ github.event.inputs.docker_repo_name
}}/gravitino-iceberg-rest" >> $GITHUB_ENV
+ elif [ "${{ github.event.inputs.image }}" == "gravitino-mcp-server"
]; then
+ echo "image_type=mcp-server" >> $GITHUB_ENV
+ echo "image_name=${{ github.event.inputs.docker_repo_name
}}/gravitino-mcp-server" >> $GITHUB_ENV
fi
if [ "${{ github.event.inputs.publish-latest-tag }}" == "true" ];
then
diff --git a/dev/docker/build-docker.sh b/dev/docker/build-docker.sh
index c48607e615..9b4758e1ba 100755
--- a/dev/docker/build-docker.sh
+++ b/dev/docker/build-docker.sh
@@ -27,7 +27,7 @@ usage() {
cat << EOF
Usage:
-./build-docker.sh --platform [all|linux/amd64|linux/arm64] --type
[gravitino|hive|kerberos-hive|trino|doris|ranger|iceberg-rest-server] --image
{image_name} --tag {tag_name} --latest
+./build-docker.sh --platform [all|linux/amd64|linux/arm64] --type
[gravitino|hive|kerberos-hive|trino|doris|ranger|iceberg-rest-server|mcp-server]
--image {image_name} --tag {tag_name} --latest
Notice: You shouldn't use 'all' for the platform if you don't use the Github
action to publish the Docker image.
EOF
@@ -115,6 +115,8 @@ elif [ "${component_type}" == "ranger" ]; then
build_args="--build-arg RANGER_PACKAGE_NAME=${RANGER_PACKAGE_NAME}
--build-arg MYSQL_CONNECTOR_PACKAGE_NAME=${MYSQL_CONNECTOR_PACKAGE_NAME}
--build-arg LOG4JDBC_PACKAGE_NAME=${LOG4JDBC_PACKAGE_NAME} --build-arg
RANGER_VERSION=${RANGER_VERSION}"
elif [ "${component_type}" == "iceberg-rest-server" ]; then
. ${script_dir}/iceberg-rest-server/iceberg-rest-server-dependency.sh
+elif [ "${component_type}" == "mcp-server" ]; then
+ . ${script_dir}/mcp-server/mcp-server-dependency.sh
else
echo "ERROR : ${component_type} is not a valid component type"
usage
diff --git a/dev/docker/mcp-server/Dockerfile b/dev/docker/mcp-server/Dockerfile
new file mode 100644
index 0000000000..5826f1c085
--- /dev/null
+++ b/dev/docker/mcp-server/Dockerfile
@@ -0,0 +1,37 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+FROM python:3.10
+
+LABEL maintainer="[email protected]"
+
+WORKDIR /root/mcp-server
+
+COPY --from=ghcr.io/astral-sh/uv:latest /uv /bin/uv
+
+COPY packages/mcp-server /root/mcp-server
+
+COPY start-mcp-server.sh /root/mcp-server
+
+RUN uv venv
+
+RUN uv sync
+
+RUN uv pip install -e .
+
+ENTRYPOINT ["/bin/bash", "start-mcp-server.sh"]
diff --git a/dev/docker/mcp-server/mcp-server-dependency.sh
b/dev/docker/mcp-server/mcp-server-dependency.sh
new file mode 100755
index 0000000000..31c3529881
--- /dev/null
+++ b/dev/docker/mcp-server/mcp-server-dependency.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+set -ex
+mcp_server_dir="$(dirname "${BASH_SOURCE-$0}")"
+mcp_server_dir="$(cd "${mcp_server_dir}">/dev/null; pwd)"
+gravitino_home="$(cd "${mcp_server_dir}/../../..">/dev/null; pwd)"
+
+cd ${gravitino_home}
+./gradlew :mcp-server:clean
+
+# Removed old packages
+rm -rf "${mcp_server_dir}/packages"
+mkdir -p "${mcp_server_dir}/packages"
+
+cp -r ${gravitino_home}/mcp-server ${mcp_server_dir}/packages/mcp-server
diff --git a/dev/docker/mcp-server/start-mcp-server.sh
b/dev/docker/mcp-server/start-mcp-server.sh
new file mode 100644
index 0000000000..ed492e87b6
--- /dev/null
+++ b/dev/docker/mcp-server/start-mcp-server.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+cd /root/mcp-server
+
+uv run mcp_server $@
diff --git a/docs/docker-image-details.md b/docs/docker-image-details.md
index 7ffe3925b7..4f292babdd 100644
--- a/docs/docker-image-details.md
+++ b/docs/docker-image-details.md
@@ -98,6 +98,22 @@ Changelog
- Expose ports:
- `9001` Iceberg REST service
+## Apache Gravitino MCP server image
+
+You can deploy the Gravitino MCP server with the Docker image.
+
+Container startup commands
+
+```shell
+docker run --rm -d -p 8000:8000 apache/gravitino-mcp-server:latest --metalake
test --transport http --mcp-url http://0.0.0.0:8000/mcp
+```
+
+Changelog
+- apache/gravitino-mcp-server:1.0.0
+ - Supports read operations for `catalog`, `schema`, `table`, `fileset`,
`model`, `policy`, `topic`, `statistic`, `job`.
+ - Supports associate&disassociate tag, policy to metadata
+ - Supports submit&cancel jobs.
+
## Playground Docker image
You can use the [playground](https://github.com/apache/gravitino-playground)
to experience the whole Gravitino system with other components.
diff --git a/docs/gravitino-mcp-server.md b/docs/gravitino-mcp-server.md
index ca0f021184..7eed314e68 100644
--- a/docs/gravitino-mcp-server.md
+++ b/docs/gravitino-mcp-server.md
@@ -51,6 +51,10 @@ Or start a HTTP MCP server by `uv run mcp_server --metalake
test --uri http://12
}
```
+### Docker instructions
+
+You could start Gravitino MCP server by docker image, `docker run -p 8000:8000
apache/gravitino-mcp-server:latest --metalake test --transport http --mcp-url
http://0.0.0.0:8000/mcp`. Please note that the MCP server in docker container
doesn't support `stdio` transport mode.
+
### Supported tools
Gravitino MCP server supports the following tools, and you could export tool
by tag.
diff --git a/docs/index.md b/docs/index.md
index 092744ea1f..ec081359b3 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -187,6 +187,12 @@ Gravitino provides security configurations for Gravitino,
including HTTPS, authe
* [Access Control](./security/access-control.md): provides access control
configurations.
* [CORS](./security/how-to-use-cors.md): provides CORS configurations.
+### Gravitino MCP server
+
+Gravitino MCP server provides the ability to manage Gravitino metadata for AI
tools.
+
+* [Gravitino MCP server](./gravitino-mcp-server.md): a complete guide to using
the Gravitino MCP server.
+
### Programming guides
* [Gravitino Open API](./api/rest/gravitino-rest-api): provides the complete
Open API definition of Gravitino.