Merge branch 'main' into feat/mcp-server-v1-final

Resolved conflicts:
- Removed old mcp_server/graphiti_mcp_server.py (moved to src/)
- Kept our uv.lock with MCP dependencies
This commit is contained in:
Daniel Chalef 2025-10-29 18:31:42 -07:00
commit 89e6e7c354
9 changed files with 154 additions and 147 deletions

View file

@ -1,73 +0,0 @@
name: Build and Push MCP Server Docker Image
on:
push:
paths:
- "mcp_server/pyproject.toml"
branches:
- main
pull_request:
paths:
- "mcp_server/pyproject.toml"
branches:
- main
workflow_dispatch:
inputs:
push_image:
description: "Push image to registry (unchecked for testing)"
required: false
default: false
type: boolean
env:
REGISTRY: docker.io
IMAGE_NAME: zepai/knowledge-graph-mcp
jobs:
build-and-push:
runs-on: depot-ubuntu-24.04-small
environment: development
permissions:
contents: read
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Extract version from pyproject.toml
id: version
run: |
VERSION=$(python -c "import tomllib; print(tomllib.load(open('mcp_server/pyproject.toml', 'rb'))['project']['version'])")
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "tag=v$VERSION" >> $GITHUB_OUTPUT
- name: Log in to Docker Hub
if: github.event_name != 'pull_request' && (github.event_name != 'workflow_dispatch' || inputs.push_image)
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Set up Depot CLI
uses: depot/setup-action@v1
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=ref,event=pr
type=raw,value=${{ steps.version.outputs.tag }}
type=raw,value=latest,enable={{is_default_branch}}
- name: Depot build and push image
uses: depot/build-push-action@v1
with:
project: v9jv1mlpwc
context: ./mcp_server
platforms: linux/amd64,linux/arm64
push: ${{ github.event_name != 'pull_request' && (github.event_name != 'workflow_dispatch' || inputs.push_image) }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

View file

@ -0,0 +1,74 @@
name: Release MCP Server
on:
push:
tags: ["mcp-v*.*.*"]
env:
REGISTRY: docker.io
IMAGE_NAME: zepai/knowledge-graph-mcp
jobs:
release:
runs-on: depot-ubuntu-24.04-small
permissions:
contents: write
id-token: write
environment:
name: release
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Python 3.11
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Extract and validate version
id: version
run: |
TAG_VERSION=${GITHUB_REF#refs/tags/mcp-v}
if ! [[ $TAG_VERSION =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "Tag must follow semantic versioning: mcp-vX.Y.Z"
exit 1
fi
PROJECT_VERSION=$(python -c "import tomllib; print(tomllib.load(open('mcp_server/pyproject.toml', 'rb'))['project']['version'])")
if [ "$TAG_VERSION" != "$PROJECT_VERSION" ]; then
echo "Tag version mcp-v$TAG_VERSION does not match mcp_server/pyproject.toml version $PROJECT_VERSION"
exit 1
fi
echo "version=$PROJECT_VERSION" >> $GITHUB_OUTPUT
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Set up Depot CLI
uses: depot/setup-action@v1
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=raw,value=${{ steps.version.outputs.version }}
type=raw,value=latest
- name: Build and push Docker image
uses: depot/build-push-action@v1
with:
project: v9jv1mlpwc
context: ./mcp_server
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

View file

@ -14,8 +14,8 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
""" """
import datetime
import asyncio import asyncio
import datetime
import logging import logging
from typing import TYPE_CHECKING, Any from typing import TYPE_CHECKING, Any
@ -236,10 +236,10 @@ class FalkorDriver(GraphDriver):
async def health_check(self) -> None: async def health_check(self) -> None:
"""Check FalkorDB connectivity by running a simple query.""" """Check FalkorDB connectivity by running a simple query."""
try: try:
await self.execute_query("MATCH (n) RETURN 1 LIMIT 1") await self.execute_query('MATCH (n) RETURN 1 LIMIT 1')
return None return None
except Exception as e: except Exception as e:
print(f"FalkorDB health check failed: {e}") print(f'FalkorDB health check failed: {e}')
raise raise
@staticmethod @staticmethod

View file

@ -77,14 +77,12 @@ class GraphOperationsInterface(BaseModel):
async def node_load_embeddings_bulk( async def node_load_embeddings_bulk(
self, self,
_cls: Any,
driver: Any, driver: Any,
transaction: Any,
nodes: list[Any], nodes: list[Any],
batch_size: int = 100, batch_size: int = 100,
) -> None: ) -> dict[str, list[float]]:
""" """
Load embedding vectors for many nodes in batches. Mutates the provided node instances. Load embedding vectors for many nodes in batches.
""" """
raise NotImplementedError raise NotImplementedError
@ -183,13 +181,11 @@ class GraphOperationsInterface(BaseModel):
async def edge_load_embeddings_bulk( async def edge_load_embeddings_bulk(
self, self,
_cls: Any,
driver: Any, driver: Any,
transaction: Any,
edges: list[Any], edges: list[Any],
batch_size: int = 100, batch_size: int = 100,
) -> None: ) -> dict[str, list[float]]:
""" """
Load embedding vectors for many edges in batches. Mutates the provided edge instances. Load embedding vectors for many edges in batches
""" """
raise NotImplementedError raise NotImplementedError

View file

@ -79,5 +79,5 @@ class Neo4jDriver(GraphDriver):
await self.client.verify_connectivity() await self.client.verify_connectivity()
return None return None
except Exception as e: except Exception as e:
print(f"Neo4j health check failed: {e}") print(f'Neo4j health check failed: {e}')
raise raise

View file

@ -1879,7 +1879,9 @@ def maximal_marginal_relevance(
async def get_embeddings_for_nodes( async def get_embeddings_for_nodes(
driver: GraphDriver, nodes: list[EntityNode] driver: GraphDriver, nodes: list[EntityNode]
) -> dict[str, list[float]]: ) -> dict[str, list[float]]:
if driver.provider == GraphProvider.NEPTUNE: if driver.graph_operations_interface:
return await driver.graph_operations_interface.node_load_embeddings_bulk(driver, nodes)
elif driver.provider == GraphProvider.NEPTUNE:
query = """ query = """
MATCH (n:Entity) MATCH (n:Entity)
WHERE n.uuid IN $node_uuids WHERE n.uuid IN $node_uuids
@ -1949,7 +1951,9 @@ async def get_embeddings_for_communities(
async def get_embeddings_for_edges( async def get_embeddings_for_edges(
driver: GraphDriver, edges: list[EntityEdge] driver: GraphDriver, edges: list[EntityEdge]
) -> dict[str, list[float]]: ) -> dict[str, list[float]]:
if driver.provider == GraphProvider.NEPTUNE: if driver.graph_operations_interface:
return await driver.graph_operations_interface.edge_load_embeddings_bulk(driver, edges)
elif driver.provider == GraphProvider.NEPTUNE:
query = """ query = """
MATCH (n:Entity)-[e:RELATES_TO]-(m:Entity) MATCH (n:Entity)-[e:RELATES_TO]-(m:Entity)
WHERE e.uuid IN $edge_uuids WHERE e.uuid IN $edge_uuids

View file

@ -214,12 +214,10 @@ async def add_nodes_and_edges_bulk_tx(
edges.append(edge_data) edges.append(edge_data)
if driver.graph_operations_interface: if driver.graph_operations_interface:
await driver.graph_operations_interface.episodic_node_save_bulk( await driver.graph_operations_interface.episodic_node_save_bulk(None, driver, tx, episodes)
None, driver, tx, episodic_nodes
)
await driver.graph_operations_interface.node_save_bulk(None, driver, tx, nodes) await driver.graph_operations_interface.node_save_bulk(None, driver, tx, nodes)
await driver.graph_operations_interface.episodic_edge_save_bulk( await driver.graph_operations_interface.episodic_edge_save_bulk(
None, driver, tx, episodic_edges None, driver, tx, [edge.model_dump() for edge in episodic_edges]
) )
await driver.graph_operations_interface.edge_save_bulk(None, driver, tx, edges) await driver.graph_operations_interface.edge_save_bulk(None, driver, tx, edges)

View file

@ -1,7 +1,7 @@
[project] [project]
name = "graphiti-core" name = "graphiti-core"
description = "A temporal graph building library" description = "A temporal graph building library"
version = "0.22.0" version = "0.22.1pre2"
authors = [ authors = [
{ name = "Paul Paliychuk", email = "paul@getzep.com" }, { name = "Paul Paliychuk", email = "paul@getzep.com" },
{ name = "Preston Rasmussen", email = "preston@getzep.com" }, { name = "Preston Rasmussen", email = "preston@getzep.com" },

View file

@ -431,6 +431,14 @@
"created_at": "2025-10-22T09:52:01Z", "created_at": "2025-10-22T09:52:01Z",
"repoId": 840056306, "repoId": 840056306,
"pullRequestNo": 1020 "pullRequestNo": 1020
},
{
"name": "didier-durand",
"id": 2927957,
"comment_id": 3460571645,
"created_at": "2025-10-29T09:31:25Z",
"repoId": 840056306,
"pullRequestNo": 1028
} }
] ]
} }