Skip to content

Commit 5b966bf

Browse files
tuhaihemy-ship-it
authored andcommitted
Configure: add --enable-mcp-server option
This commit integrates the MCP (Model Context Protocol) server component into the Cloudberry build system, allowing users to optionally build and install it using the standard configure/make workflow. What: - Added --enable-mcp-server option to configure.ac with dependency checks for Python 3.10+ and uv/pip package managers - Created mcp-server/Makefile to build Python wheel packages and install them to the configured prefix directory - Modified GNUmakefile.in to conditionally build, install, and clean mcp-server based on the configure flag - Updated mcp-server/pyproject.toml to require Python 3.11 How: - The Makefile uses Python's standard build tools (uv or pip) to create wheel packages from pyproject.toml - Installation uses --target to place packages in the correct site-packages directory with all dependencies - A wrapper script is generated to set PYTHONPATH and invoke the server module - Platform support is limited to Linux (PORTNAME=linux) as mcp-server is not intended for macOS production use Usage: ./configure --enable-mcp-server --prefix=/path/to/install make make install cloudberry-mcp-server --help Compatibility: - Requires Python 3.10 or later (Python 3.11 recommended) - Rocky Linux 9 users need to install python3.11+ alongside the system Python 3.9 to avoid conflicts with Cloudberry's Python dependencies
1 parent e51dd08 commit 5b966bf

File tree

4 files changed

+311
-1
lines changed

4 files changed

+311
-1
lines changed

GNUmakefile.in

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ ifeq ($(enable_pax), yes)
3737
endif
3838
$(MAKE) -C gpMgmt all
3939
$(MAKE) -C gpcontrib all
40+
ifeq ($(enable_mcp_server), yes)
41+
$(MAKE) -C mcp-server all
42+
endif
4043
+@echo "All of Apache Cloudberry successfully made. Ready to install."
4144

4245
docs:
@@ -84,6 +87,9 @@ ifeq ($(with_openssl), yes)
8487
endif
8588
$(MAKE) -C gpMgmt $@
8689
$(MAKE) -C gpcontrib $@
90+
ifeq ($(enable_mcp_server), yes)
91+
$(MAKE) -C mcp-server $@
92+
endif
8793
+@echo "Apache Cloudberry installation complete."
8894

8995
install-docs:
@@ -116,6 +122,9 @@ clean:
116122
# gpAux/Makefile is the entry point for the enterprise build, which ends up
117123
# calling top-level configure and this Makefile
118124
$(MAKE) -C gpMgmt $@
125+
ifeq ($(enable_mcp_server), yes)
126+
$(MAKE) -C mcp-server $@
127+
endif
119128

120129
# Important: distclean `src' last, otherwise Makefile.global
121130
# will be gone too soon.
@@ -125,6 +134,9 @@ distclean maintainer-clean:
125134
$(MAKE) -C gpcontrib $@
126135
$(MAKE) -C config $@
127136
$(MAKE) -C gpMgmt $@
137+
ifeq ($(enable_mcp_server), yes)
138+
$(MAKE) -C mcp-server $@
139+
endif
128140
$(MAKE) -C src $@
129141
rm -rf tmp_install/
130142
# Garbage from autoconf:

configure

Lines changed: 130 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -744,7 +744,6 @@ with_gssapi
744744
with_pythonsrc_ext
745745
PIP3
746746
CURL
747-
PYTHON3
748747
with_python
749748
with_perl
750749
with_tcl
@@ -759,6 +758,9 @@ ZSTD_LIBS
759758
ZSTD_CFLAGS
760759
PROTOBUF_LIBS
761760
PROTOBUF_CFLAGS
761+
UV
762+
PYTHON3
763+
enable_mcp_server
762764
enable_preload_ic_module
763765
enable_ic_proxy
764766
enable_external_fts
@@ -911,6 +913,7 @@ enable_gpcloud
911913
enable_external_fts
912914
enable_ic_proxy
913915
enable_preload_ic_module
916+
enable_mcp_server
914917
enable_pax
915918
enable_thread_safety
916919
with_icu
@@ -1633,6 +1636,7 @@ Optional Features:
16331636
library)
16341637
--disable-preload-ic-module
16351638
disable preload interconnect module
1639+
--enable-mcp-server enable MCP server support
16361640
--enable-pax enable PAX support
16371641
--disable-thread-safety disable thread-safety in client libraries
16381642
--enable-openssl-redirect
@@ -9245,6 +9249,131 @@ fi
92459249
$as_echo "checking whether to build with preload ic module ... $enable_preload_ic_module" >&6; }
92469250

92479251

9252+
#
9253+
# mcp-server
9254+
#
9255+
9256+
9257+
# Check whether --enable-mcp-server was given.
9258+
if test "${enable_mcp_server+set}" = set; then :
9259+
enableval=$enable_mcp_server;
9260+
case $enableval in
9261+
yes)
9262+
9263+
$as_echo "#define ENABLE_MCP_SERVER 1" >>confdefs.h
9264+
9265+
;;
9266+
no)
9267+
:
9268+
;;
9269+
*)
9270+
as_fn_error $? "no argument expected for --enable-mcp-server option" "$LINENO" 5
9271+
;;
9272+
esac
9273+
9274+
else
9275+
enable_mcp_server=no
9276+
9277+
fi
9278+
9279+
9280+
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: checking whether to build with MCP server... $enable_mcp_server" >&5
9281+
$as_echo "checking whether to build with MCP server... $enable_mcp_server" >&6; }
9282+
9283+
9284+
# Check for required dependencies when mcp-server is enabled
9285+
if test "$enable_mcp_server" = yes; then
9286+
# Extract the first word of "python3", so it can be a program name with args.
9287+
set dummy python3; ac_word=$2
9288+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
9289+
$as_echo_n "checking for $ac_word... " >&6; }
9290+
if ${ac_cv_path_PYTHON3+:} false; then :
9291+
$as_echo_n "(cached) " >&6
9292+
else
9293+
case $PYTHON3 in
9294+
[\\/]* | ?:[\\/]*)
9295+
ac_cv_path_PYTHON3="$PYTHON3" # Let the user override the test with a path.
9296+
;;
9297+
*)
9298+
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
9299+
for as_dir in $PATH
9300+
do
9301+
IFS=$as_save_IFS
9302+
test -z "$as_dir" && as_dir=.
9303+
for ac_exec_ext in '' $ac_executable_extensions; do
9304+
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
9305+
ac_cv_path_PYTHON3="$as_dir/$ac_word$ac_exec_ext"
9306+
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
9307+
break 2
9308+
fi
9309+
done
9310+
done
9311+
IFS=$as_save_IFS
9312+
9313+
;;
9314+
esac
9315+
fi
9316+
PYTHON3=$ac_cv_path_PYTHON3
9317+
if test -n "$PYTHON3"; then
9318+
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON3" >&5
9319+
$as_echo "$PYTHON3" >&6; }
9320+
else
9321+
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
9322+
$as_echo "no" >&6; }
9323+
fi
9324+
9325+
9326+
if test -z "$PYTHON3"; then
9327+
as_fn_error $? "python3 is required for --enable-mcp-server but was not found" "$LINENO" 5
9328+
fi
9329+
9330+
# Check for uv (Python package manager)
9331+
# Extract the first word of "uv", so it can be a program name with args.
9332+
set dummy uv; ac_word=$2
9333+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
9334+
$as_echo_n "checking for $ac_word... " >&6; }
9335+
if ${ac_cv_path_UV+:} false; then :
9336+
$as_echo_n "(cached) " >&6
9337+
else
9338+
case $UV in
9339+
[\\/]* | ?:[\\/]*)
9340+
ac_cv_path_UV="$UV" # Let the user override the test with a path.
9341+
;;
9342+
*)
9343+
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
9344+
for as_dir in $PATH
9345+
do
9346+
IFS=$as_save_IFS
9347+
test -z "$as_dir" && as_dir=.
9348+
for ac_exec_ext in '' $ac_executable_extensions; do
9349+
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
9350+
ac_cv_path_UV="$as_dir/$ac_word$ac_exec_ext"
9351+
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
9352+
break 2
9353+
fi
9354+
done
9355+
done
9356+
IFS=$as_save_IFS
9357+
9358+
;;
9359+
esac
9360+
fi
9361+
UV=$ac_cv_path_UV
9362+
if test -n "$UV"; then
9363+
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $UV" >&5
9364+
$as_echo "$UV" >&6; }
9365+
else
9366+
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
9367+
$as_echo "no" >&6; }
9368+
fi
9369+
9370+
9371+
if test -z "$UV"; then
9372+
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: uv not found. MCP server build will attempt to use pip as fallback." >&5
9373+
$as_echo "$as_me: WARNING: uv not found. MCP server build will attempt to use pip as fallback." >&2;}
9374+
fi
9375+
fi
9376+
92489377
#
92499378
# pax support
92509379
#

configure.ac

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -942,6 +942,30 @@ PGAC_ARG_BOOL(enable, preload-ic-module, yes,
942942
AC_MSG_RESULT([checking whether to build with preload ic module ... $enable_preload_ic_module])
943943
AC_SUBST(enable_preload_ic_module)
944944

945+
#
946+
# mcp-server
947+
#
948+
PGAC_ARG_BOOL(enable, mcp-server, no,
949+
[enable MCP server support],
950+
[AC_DEFINE(ENABLE_MCP_SERVER, 1,
951+
[Define to 1 to build with MCP server support (--enable-mcp-server)])])
952+
AC_MSG_RESULT([checking whether to build with MCP server... $enable_mcp_server])
953+
AC_SUBST(enable_mcp_server)
954+
955+
# Check for required dependencies when mcp-server is enabled
956+
if test "$enable_mcp_server" = yes; then
957+
AC_PATH_PROG([PYTHON3], [python3])
958+
if test -z "$PYTHON3"; then
959+
AC_MSG_ERROR([python3 is required for --enable-mcp-server but was not found])
960+
fi
961+
962+
# Check for uv (Python package manager)
963+
AC_PATH_PROG([UV], [uv])
964+
if test -z "$UV"; then
965+
AC_MSG_WARN([uv not found. MCP server build will attempt to use pip as fallback.])
966+
fi
967+
fi
968+
945969
#
946970
# pax support
947971
#

mcp-server/Makefile

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
#
18+
# Makefile for Apache Cloudberry MCP Server
19+
#
20+
# This Makefile integrates the Python-based MCP server into the
21+
# Cloudberry build system. It uses uv (preferred) or pip for
22+
# dependency management and installation.
23+
#
24+
25+
# Get build configuration from top-level Makefile
26+
subdir = mcp-server
27+
top_builddir = ..
28+
include $(top_builddir)/src/Makefile.global
29+
30+
# Installation directories
31+
# Note: Use $(prefix) directly to avoid automatic /postgresql suffix added by $(datadir)
32+
MCP_SERVER_BIN_DIR = $(prefix)/bin
33+
34+
# Python and package manager
35+
# Note: fastmcp requires Python 3.10+
36+
PYTHON3 ?= python3.11
37+
UV ?= uv
38+
PIP3 ?= pip3.11
39+
40+
# Determine which package manager to use
41+
USE_UV := $(shell command -v $(UV) 2> /dev/null)
42+
43+
# Build directory
44+
BUILD_DIR = dist
45+
VENV_DIR = .venv
46+
47+
.PHONY: all build install installdirs uninstall clean distclean
48+
49+
all: build
50+
51+
# Build the MCP server package
52+
build:
53+
@echo "Building Apache Cloudberry MCP Server..."
54+
ifdef USE_UV
55+
@echo "Using uv for build..."
56+
$(UV) build
57+
else
58+
@echo "Using pip for build..."
59+
$(PYTHON3) -m pip install --upgrade build
60+
$(PYTHON3) -m build
61+
endif
62+
@echo "MCP Server build complete."
63+
64+
# Install the MCP server
65+
install: build installdirs
66+
@echo "Installing Apache Cloudberry MCP Server..."
67+
ifdef USE_UV
68+
@echo "Installing with uv..."
69+
$(UV) pip install --system --prefix=$(DESTDIR)$(prefix) $(BUILD_DIR)/*.whl
70+
else
71+
@echo "Installing with pip..."
72+
$(PIP3) install --target=$(DESTDIR)$(prefix)/lib/python$$($(PYTHON3) -c "import sys; print('%d.%d' % (sys.version_info.major, sys.version_info.minor))")/site-packages $(BUILD_DIR)/*.whl
73+
endif
74+
@# Create a wrapper script for easier invocation
75+
@echo '#!/bin/sh' > '$(DESTDIR)$(MCP_SERVER_BIN_DIR)/cloudberry-mcp-server'
76+
@echo '# Wrapper script for Apache Cloudberry MCP Server' >> '$(DESTDIR)$(MCP_SERVER_BIN_DIR)/cloudberry-mcp-server'
77+
@echo '' >> '$(DESTDIR)$(MCP_SERVER_BIN_DIR)/cloudberry-mcp-server'
78+
@echo '# Detect Python version and set PYTHONPATH' >> '$(DESTDIR)$(MCP_SERVER_BIN_DIR)/cloudberry-mcp-server'
79+
@echo 'PYTHON_VERSION=$$($(PYTHON3) -c "import sys; print(\"python%d.%d\" % (sys.version_info.major, sys.version_info.minor))")' >> '$(DESTDIR)$(MCP_SERVER_BIN_DIR)/cloudberry-mcp-server'
80+
@echo 'GPHOME="$$(cd "$$(dirname "$$0")/.." && pwd)"' >> '$(DESTDIR)$(MCP_SERVER_BIN_DIR)/cloudberry-mcp-server'
81+
@echo 'export PYTHONPATH="$$GPHOME/lib/$$PYTHON_VERSION/site-packages:$$PYTHONPATH"' >> '$(DESTDIR)$(MCP_SERVER_BIN_DIR)/cloudberry-mcp-server'
82+
@echo '' >> '$(DESTDIR)$(MCP_SERVER_BIN_DIR)/cloudberry-mcp-server'
83+
@echo 'exec $(PYTHON3) -m cbmcp.server "$$@"' >> '$(DESTDIR)$(MCP_SERVER_BIN_DIR)/cloudberry-mcp-server'
84+
@chmod +x '$(DESTDIR)$(MCP_SERVER_BIN_DIR)/cloudberry-mcp-server'
85+
@echo "MCP Server installation complete."
86+
@echo "Installed to: $(DESTDIR)$(prefix)"
87+
@echo "You can run it with: cloudberry-mcp-server"
88+
89+
# Create installation directories
90+
installdirs:
91+
$(MKDIR_P) '$(DESTDIR)$(MCP_SERVER_BIN_DIR)'
92+
93+
# Uninstall the MCP server
94+
uninstall:
95+
@echo "Uninstalling Apache Cloudberry MCP Server..."
96+
rm -f '$(DESTDIR)$(MCP_SERVER_BIN_DIR)/cloudberry-mcp-server'
97+
ifdef USE_UV
98+
-$(UV) pip uninstall --system cloudberry-mcp-server 2>/dev/null || true
99+
else
100+
-$(PIP3) uninstall -y cloudberry-mcp-server 2>/dev/null || true
101+
endif
102+
@echo "MCP Server uninstalled."
103+
104+
# Clean build artifacts
105+
clean:
106+
@echo "Cleaning MCP Server build artifacts..."
107+
rm -rf $(BUILD_DIR)
108+
rm -rf $(VENV_DIR)
109+
rm -rf build
110+
rm -rf *.egg-info
111+
rm -rf src/*.egg-info
112+
find . -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true
113+
find . -type f -name '*.pyc' -delete 2>/dev/null || true
114+
find . -type f -name '*.pyo' -delete 2>/dev/null || true
115+
@echo "MCP Server cleaned."
116+
117+
# Distclean - remove all generated files
118+
distclean: clean
119+
@echo "Deep cleaning MCP Server..."
120+
rm -rf .pytest_cache
121+
rm -rf .coverage
122+
rm -rf htmlcov
123+
@echo "MCP Server distclean complete."
124+
125+
# Help target
126+
help:
127+
@echo "Apache Cloudberry MCP Server Makefile"
128+
@echo ""
129+
@echo "Available targets:"
130+
@echo " all - Build the MCP server (default)"
131+
@echo " build - Build the MCP server package"
132+
@echo " install - Install the MCP server"
133+
@echo " uninstall - Uninstall the MCP server"
134+
@echo " clean - Remove build artifacts"
135+
@echo " distclean - Remove all generated files"
136+
@echo " help - Show this help message"
137+
@echo ""
138+
@echo "Configuration:"
139+
@echo " PYTHON3 = $(PYTHON3)"
140+
ifdef USE_UV
141+
@echo " UV = $(UV) (using uv)"
142+
else
143+
@echo " PIP3 = $(PIP3) (using pip)"
144+
endif
145+
@echo " Install to = $(prefix)"

0 commit comments

Comments
 (0)