Skip to content

Commit 80b0207

Browse files
committed
MCP: Add example about MCP Alchemy
1 parent 960f7a1 commit 80b0207

File tree

4 files changed

+96
-1
lines changed

4 files changed

+96
-1
lines changed

framework/mcp/README.md

+7
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ program.
3636
Server for JDBC] from the [quarkus-mcp-servers] package, providing a range
3737
of tools. It is written in Java, to be invoked with [JBang].
3838

39+
- `example_mcp_alchemy.py`: Exercise communication using the [MCP Alchemy] MCP
40+
server package, providing a range of tools. It is written in Python, and uses
41+
[SQLAlchemy] and the [CrateDB SQLAlchemy dialect].
42+
3943
## Resources
4044

4145
- Read a [brief introduction to MCP] by ByteByteGo.
@@ -124,10 +128,12 @@ unlocking more details and features.
124128
[Claude Desktop configuration]: https://github.com/modelcontextprotocol/servers?tab=readme-ov-file#using-an-mcp-client
125129
[connecting to an already running MCP server]: https://github.com/modelcontextprotocol/python-sdk/issues/145
126130
[CrateDB]: https://cratedb.com/database
131+
[CrateDB SQLAlchemy dialect]: https://cratedb.com/docs/sqlalchemy-cratedb/
127132
[DBHub]: https://github.com/bytebase/dbhub
128133
[Introduction to MCP]: https://modelcontextprotocol.io/introduction
129134
[JBang]: https://www.jbang.dev/
130135
[MCP]: https://modelcontextprotocol.io/
136+
[MCP Alchemy]: https://github.com/runekaagaard/mcp-alchemy
131137
[MCP Python SDK]: https://github.com/modelcontextprotocol/python-sdk
132138
[MCP SSE]: https://github.com/sidharthrajaram/mcp-sse
133139
[Model Context Protocol (MCP) @ CrateDB]: https://github.com/crate/crate-clients-tools/discussions/234
@@ -137,5 +143,6 @@ unlocking more details and features.
137143
[npx]: https://docs.npmjs.com/cli/v11/commands/npx
138144
[oterm configuration]: https://ggozad.github.io/oterm/tools/mcp/
139145
[quarkus-mcp-servers]: https://github.com/quarkiverse/quarkus-mcp-servers
146+
[SQLAlchemy]: https://sqlalchemy.org/
140147
[uv]: https://docs.astral.sh/uv/
141148
[Writing MCP Clients]: https://github.com/modelcontextprotocol/python-sdk?tab=readme-ov-file#writing-mcp-clients

framework/mcp/example_mcp_alchemy.py

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# MCP Alchemy Model Context Protocol Server for CrateDB
2+
# https://github.com/runekaagaard/mcp-alchemy
3+
#
4+
# Derived from:
5+
# https://github.com/modelcontextprotocol/python-sdk?tab=readme-ov-file#writing-mcp-clients
6+
from cratedb_toolkit.util import DatabaseAdapter
7+
from mcp import ClientSession, StdioServerParameters
8+
from mcp.client.stdio import stdio_client
9+
import where
10+
11+
from mcp_utils import McpDatabaseConversation
12+
13+
14+
async def run():
15+
# Create server parameters for stdio connection.
16+
server_params = StdioServerParameters(
17+
command=where.first("mcp-alchemy"),
18+
args=[],
19+
env={"DB_URL": "crate://crate@localhost:4200/?schema=testdrive"},
20+
)
21+
22+
async with stdio_client(server_params) as (read, write):
23+
async with ClientSession(
24+
read, write
25+
) as session:
26+
# Initialize the connection.
27+
await session.initialize()
28+
29+
client = McpDatabaseConversation(session)
30+
await client.inquire()
31+
32+
print("## MCP server conversations")
33+
print()
34+
35+
# Provision database content.
36+
db = DatabaseAdapter("crate://crate@localhost:4200/")
37+
db.run_sql("CREATE TABLE IF NOT EXISTS mcp_alchemy (id INT, data TEXT)")
38+
db.run_sql("INSERT INTO mcp_alchemy (id, data) VALUES (42, 'Hotzenplotz')")
39+
db.refresh_table("mcp_alchemy")
40+
41+
# Call a few tools.
42+
await client.call_tool("execute_query", arguments={"query": "SELECT * FROM sys.summits ORDER BY height DESC LIMIT 3"})
43+
await client.call_tool("all_table_names", arguments={})
44+
await client.call_tool("filter_table_names", arguments={"q": "mcp"})
45+
await client.call_tool("schema_definitions", arguments={"table_names": ["mcp_alchemy"]})
46+
47+
48+
if __name__ == "__main__":
49+
import asyncio
50+
51+
asyncio.run(run())

framework/mcp/requirements.txt

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
11
cratedb-toolkit
2-
mcp<1.5
2+
mcp<1.6
3+
mcp-alchemy @ git+https://github.com/runekaagaard/mcp-alchemy.git@b85aae6; python_version>='3.12'
4+
sqlalchemy-cratedb>=0.42.0.dev1
5+
where

framework/mcp/test.py

+34
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import subprocess
55
import sys
66

7+
import pytest
78
from cratedb_toolkit.util import DatabaseAdapter
89

910

@@ -116,3 +117,36 @@ def test_dbhub():
116117
assert b"Getting prompt: explain_db" in p.stdout
117118
assert b"Table: mcp_dbhub in schema 'testdrive'" in p.stdout
118119
assert b"Structure:\\n- id (integer)\\n- data (text)" in p.stdout
120+
121+
122+
@pytest.mark.skipif(sys.version_info < (3, 12), reason="requires Python 3.12+")
123+
def test_mcp_alchemy():
124+
"""
125+
Validate the MCP Alchemy server works well.
126+
127+
MCP Alchemy connects Claude Desktop directly to your databases.
128+
MCP Alchemy is a MCP (model context protocol) server that gives the LLM access
129+
to and knowledge about relational databases like SQLite, Postgresql, MySQL &
130+
MariaDB, Oracle, MS-SQL, and CrateDB.
131+
132+
It is written in Python and uses SQLAlchemy.
133+
https://github.com/runekaagaard/mcp-alchemy
134+
"""
135+
p = run(f"{sys.executable} example_mcp_alchemy.py")
136+
assert p.returncode == 0
137+
138+
# Validate output specific to the MCP server.
139+
140+
# Validate output specific to CrateDB.
141+
assert b"Calling tool: execute_query" in p.stdout
142+
assert b"mountain: Mont Blanc" in p.stdout
143+
144+
assert b"Calling tool: all_table_names" in p.stdout
145+
assert b"mcp_alchemy" in p.stdout
146+
147+
assert b"Calling tool: filter_table_names" in p.stdout
148+
assert b"mcp_alchemy" in p.stdout
149+
150+
assert b"Calling tool: schema_definitions" in p.stdout
151+
assert b"id: INTEGER, nullable" in p.stdout
152+
assert b"data: VARCHAR, nullable" in p.stdout

0 commit comments

Comments
 (0)