From 9814aac1ca2327861c517cf9d2c1c33434aa3ed5 Mon Sep 17 00:00:00 2001 From: Aidan Petti Date: Mon, 24 Nov 2025 13:30:52 -0700 Subject: [PATCH] Neptune MCP Support --- mcp_server/config/config.yaml | 9 +- mcp_server/docker/Dockerfile | 7 +- mcp_server/docker/Dockerfile.standalone | 8 +- mcp_server/pyproject.toml | 4 +- mcp_server/src/config/schema.py | 31 ++ mcp_server/src/graphiti_mcp_server.py | 38 ++- mcp_server/src/services/factories.py | 79 +++++ mcp_server/tests/test_configuration.py | 3 - .../tests/test_neptune_configuration.py | 308 ++++++++++++++++++ mcp_server/tests/test_neptune_simple.py | 225 +++++++++++++ mcp_server/uv.lock | 289 +++++++++++++++- 11 files changed, 969 insertions(+), 32 deletions(-) create mode 100644 mcp_server/tests/test_neptune_configuration.py create mode 100644 mcp_server/tests/test_neptune_simple.py diff --git a/mcp_server/config/config.yaml b/mcp_server/config/config.yaml index 91f72377..d9723b45 100644 --- a/mcp_server/config/config.yaml +++ b/mcp_server/config/config.yaml @@ -71,7 +71,7 @@ embedder: model: "voyage-3" database: - provider: "falkordb" # Default: falkordb. Options: neo4j, falkordb + provider: "falkordb" # Default: falkordb. Options: neo4j, falkordb, neptune providers: falkordb: @@ -86,6 +86,13 @@ database: database: ${NEO4J_DATABASE:neo4j} use_parallel_runtime: ${USE_PARALLEL_RUNTIME:false} + neptune: + host: ${NEPTUNE_HOST:neptune-db://localhost} + aoss_host: ${AOSS_HOST} + port: ${NEPTUNE_PORT:8182} + aoss_port: ${AOSS_PORT:443} + region: ${AWS_REGION:} + graphiti: group_id: ${GRAPHITI_GROUP_ID:main} episode_id_prefix: ${EPISODE_ID_PREFIX:} diff --git a/mcp_server/docker/Dockerfile b/mcp_server/docker/Dockerfile index 936a16a0..ab19f5d8 100644 --- a/mcp_server/docker/Dockerfile +++ b/mcp_server/docker/Dockerfile @@ -33,16 +33,17 @@ ENV UV_COMPILE_BYTECODE=1 \ WORKDIR /app/mcp # Accept graphiti-core version as build argument -ARG GRAPHITI_CORE_VERSION=0.23.1 +ARG GRAPHITI_CORE_VERSION=0.24.1 # Copy project files for dependency installation COPY pyproject.toml uv.lock ./ # Remove the local path override for graphiti-core in Docker builds +# Install with falkordb and neptune extras for maximum flexibility # and regenerate lock file to match the PyPI version RUN sed -i '/\[tool\.uv\.sources\]/,/graphiti-core/d' pyproject.toml && \ if [ -n "${GRAPHITI_CORE_VERSION}" ]; then \ - sed -i "s/graphiti-core\[falkordb\]>=[0-9]\+\.[0-9]\+\.[0-9]\+$/graphiti-core[falkordb]==${GRAPHITI_CORE_VERSION}/" pyproject.toml; \ + sed -i "s/graphiti-core\[falkordb\]>=[0-9]\+\.[0-9]\+\.[0-9]\+$/graphiti-core[falkordb,neptune]==${GRAPHITI_CORE_VERSION}/" pyproject.toml; \ fi && \ echo "Regenerating lock file for PyPI graphiti-core..." && \ rm -f uv.lock && \ @@ -112,7 +113,7 @@ EOF RUN chmod +x /start-services.sh # Add Docker labels with version information -ARG MCP_SERVER_VERSION=1.0.1 +ARG MCP_SERVER_VERSION=1.0.2 ARG BUILD_DATE ARG VCS_REF LABEL org.opencontainers.image.title="FalkorDB + Graphiti MCP Server" \ diff --git a/mcp_server/docker/Dockerfile.standalone b/mcp_server/docker/Dockerfile.standalone index be16f7fa..b7d49d75 100644 --- a/mcp_server/docker/Dockerfile.standalone +++ b/mcp_server/docker/Dockerfile.standalone @@ -28,16 +28,16 @@ ENV UV_COMPILE_BYTECODE=1 \ WORKDIR /app/mcp # Accept graphiti-core version as build argument -ARG GRAPHITI_CORE_VERSION=0.23.1 +ARG GRAPHITI_CORE_VERSION=0.24.1 # Copy project files for dependency installation COPY pyproject.toml uv.lock ./ # Remove the local path override for graphiti-core in Docker builds -# Install with BOTH neo4j and falkordb extras for maximum flexibility +# Install with neo4j, falkordb, and neptune extras for maximum flexibility # and regenerate lock file to match the PyPI version RUN sed -i '/\[tool\.uv\.sources\]/,/graphiti-core/d' pyproject.toml && \ - sed -i "s/graphiti-core\[falkordb\]>=[0-9]\+\.[0-9]\+\.[0-9]\+$/graphiti-core[neo4j,falkordb]==${GRAPHITI_CORE_VERSION}/" pyproject.toml && \ + sed -i "s/graphiti-core\[falkordb\]>=[0-9]\+\.[0-9]\+\.[0-9]\+$/graphiti-core[neo4j,falkordb,neptune]==${GRAPHITI_CORE_VERSION}/" pyproject.toml && \ echo "Regenerating lock file for PyPI graphiti-core..." && \ rm -f uv.lock && \ uv lock @@ -58,7 +58,7 @@ COPY config/ ./config/ RUN mkdir -p /var/log/graphiti # Add Docker labels with version information -ARG MCP_SERVER_VERSION=1.0.1 +ARG MCP_SERVER_VERSION=1.0.2 ARG BUILD_DATE ARG VCS_REF LABEL org.opencontainers.image.title="Graphiti MCP Server (Standalone)" \ diff --git a/mcp_server/pyproject.toml b/mcp_server/pyproject.toml index ac5b4d97..18c98dbd 100644 --- a/mcp_server/pyproject.toml +++ b/mcp_server/pyproject.toml @@ -1,13 +1,13 @@ [project] name = "mcp-server" -version = "1.0.1" +version = "1.0.2" description = "Graphiti MCP Server" readme = "README.md" requires-python = ">=3.10,<4" dependencies = [ "mcp>=1.9.4", "openai>=1.91.0", - "graphiti-core[falkordb]>=0.23.1", + "graphiti-core[falkordb,neptune]>=0.23.1", "pydantic-settings>=2.0.0", "pyyaml>=6.0", "typing-extensions>=4.0.0", diff --git a/mcp_server/src/config/schema.py b/mcp_server/src/config/schema.py index 990d96c4..a67f733d 100644 --- a/mcp_server/src/config/schema.py +++ b/mcp_server/src/config/schema.py @@ -191,11 +191,42 @@ class FalkorDBProviderConfig(BaseModel): database: str = 'default_db' +class NeptuneProviderConfig(BaseModel): + """Neptune provider configuration.""" + + host: str = 'neptune-db://localhost' + aoss_host: str | None = None + port: int = Field(default=8182, ge=1, le=65535) + aoss_port: int = Field(default=443, ge=1, le=65535) + region: str | None = None + + def model_post_init(self, __context) -> None: + """Validate Neptune-specific requirements.""" + if not self.host.startswith(('neptune-db://', 'neptune-graph://')): + raise ValueError( + 'Neptune host must start with neptune-db:// or neptune-graph://\n' + 'Examples:\n' + ' - Database: neptune-db://my-cluster.us-east-1.neptune.amazonaws.com\n' + ' - Analytics: neptune-graph://g-abc123xyz' + ) + + if not self.aoss_host: + raise ValueError( + 'Neptune requires aoss_host for full-text search.\n' + 'Set AOSS_HOST environment variable or add to config:\n' + ' database:\n' + ' providers:\n' + ' neptune:\n' + ' aoss_host: "your-aoss-endpoint.us-east-1.aoss.amazonaws.com"' + ) + + class DatabaseProvidersConfig(BaseModel): """Database providers configuration.""" neo4j: Neo4jProviderConfig | None = None falkordb: FalkorDBProviderConfig | None = None + neptune: NeptuneProviderConfig | None = None class DatabaseConfig(BaseModel): diff --git a/mcp_server/src/graphiti_mcp_server.py b/mcp_server/src/graphiti_mcp_server.py index 833bc5d9..177b09ad 100644 --- a/mcp_server/src/graphiti_mcp_server.py +++ b/mcp_server/src/graphiti_mcp_server.py @@ -228,6 +228,23 @@ class GraphitiService: embedder=embedder_client, max_coroutines=self.semaphore_limit, ) + elif self.config.database.provider.lower() == 'neptune': + # For Neptune, create a NeptuneDriver instance directly + from graphiti_core.driver.neptune_driver import NeptuneDriver + + neptune_driver = NeptuneDriver( + host=db_config['host'], + aoss_host=db_config['aoss_host'], + port=db_config['port'], + aoss_port=db_config['aoss_port'], + ) + + self.client = Graphiti( + graph_driver=neptune_driver, + llm_client=llm_client, + embedder=embedder_client, + max_coroutines=self.semaphore_limit, + ) else: # For Neo4j (default), use the original approach self.client = Graphiti( @@ -266,6 +283,25 @@ class GraphitiService: f' - Or run Neo4j manually: docker run -p 7474:7474 -p 7687:7687 neo4j:latest\n\n' f'{"=" * 70}\n' ) from db_error + elif db_provider.lower() == 'neptune': + raise RuntimeError( + f'\n{"=" * 70}\n' + f'Database Connection Error: Neptune is not accessible\n' + f'{"=" * 70}\n\n' + f'Neptune: {db_config.get("host", "unknown")}\n' + f'OpenSearch: {db_config.get("aoss_host", "unknown")}\n\n' + f'Troubleshooting:\n' + f' 1. Verify Neptune endpoint format (neptune-db:// or neptune-graph://)\n' + f' 2. Check AWS credentials: aws sts get-caller-identity\n' + f' 3. Verify security groups allow access\n' + f' 4. Confirm OpenSearch Serverless endpoint is accessible\n' + f' 5. Check IAM permissions (neptune-db:*, aoss:*, neptune-graph:*)\n\n' + f'AWS Setup:\n' + f' - Region: {db_config.get("region", "not set")}\n' + f' - Run: aws neptune describe-db-clusters (for Database)\n' + f' - Run: aws neptune-graph list-graphs (for Analytics)\n\n' + f'{"=" * 70}\n' + ) from db_error else: raise RuntimeError( f'\n{"=" * 70}\n' @@ -806,7 +842,7 @@ async def initialize_server() -> ServerConfig: ) parser.add_argument( '--database-provider', - choices=['neo4j', 'falkordb'], + choices=['neo4j', 'falkordb', 'neptune'], help='Database provider to use', ) diff --git a/mcp_server/src/services/factories.py b/mcp_server/src/services/factories.py index 02f19e35..5c7bf4f1 100644 --- a/mcp_server/src/services/factories.py +++ b/mcp_server/src/services/factories.py @@ -16,6 +16,14 @@ try: except ImportError: HAS_FALKOR = False +# Try to import NeptuneDriver if available +try: + from graphiti_core.driver.neptune_driver import NeptuneDriver # noqa: F401 + + HAS_NEPTUNE = True +except ImportError: + HAS_NEPTUNE = False + # Kuzu support removed - FalkorDB is now the default from graphiti_core.embedder import EmbedderClient, OpenAIEmbedder from graphiti_core.llm_client import LLMClient, OpenAIClient @@ -433,5 +441,76 @@ class DatabaseDriverFactory: 'database': falkor_config.database, } + case 'neptune': + if not HAS_NEPTUNE: + raise ValueError( + 'Neptune driver not available. Install with:\n' + ' pip install graphiti-core[neptune]\n' + 'or:\n' + ' uv add graphiti-core[neptune]' + ) + + # Validate AWS credentials early + import boto3 + + try: + session = boto3.Session() + credentials = session.get_credentials() + if not credentials: + raise ValueError( + 'AWS credentials not configured for Neptune.\n' + 'Configure using one of:\n' + ' 1. AWS CLI: aws configure\n' + ' 2. Environment: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY\n' + ' 3. IAM role (if running on AWS)\n' + ' 4. Credentials file: ~/.aws/credentials' + ) + + region = session.region_name + if not region: + import logging + + logger = logging.getLogger(__name__) + logger.warning('AWS region not detected, using default from config') + except Exception as e: + raise ValueError(f'AWS credential error: {e}') from e + + # Load Neptune config + if config.providers.neptune: + neptune_config = config.providers.neptune + else: + from config.schema import NeptuneProviderConfig + + neptune_config = NeptuneProviderConfig() + + # Environment overrides + import os + + host = os.environ.get('NEPTUNE_HOST', neptune_config.host) + aoss_host = os.environ.get('AOSS_HOST', neptune_config.aoss_host) + port = int(os.environ.get('NEPTUNE_PORT', str(neptune_config.port))) + aoss_port = int(os.environ.get('AOSS_PORT', str(neptune_config.aoss_port))) + region_override = os.environ.get('AWS_REGION', region or neptune_config.region) + + if not aoss_host: + raise ValueError( + 'Neptune requires AOSS_HOST for full-text search.\n' + 'Set it in config or environment variable.' + ) + + import logging + + logger = logging.getLogger(__name__) + logger.info(f'Creating Neptune driver for {host} with region {region_override}') + + return { + 'driver': 'neptune', + 'host': host, + 'aoss_host': aoss_host, + 'port': port, + 'aoss_port': aoss_port, + 'region': region_override, + } + case _: raise ValueError(f'Unsupported Database provider: {provider}') diff --git a/mcp_server/tests/test_configuration.py b/mcp_server/tests/test_configuration.py index 5876c1ed..e540817e 100644 --- a/mcp_server/tests/test_configuration.py +++ b/mcp_server/tests/test_configuration.py @@ -6,9 +6,6 @@ import os import sys from pathlib import Path -# Add the current directory to the path -sys.path.insert(0, str(Path(__file__).parent.parent / 'src')) - from config.schema import GraphitiConfig from services.factories import DatabaseDriverFactory, EmbedderFactory, LLMClientFactory diff --git a/mcp_server/tests/test_neptune_configuration.py b/mcp_server/tests/test_neptune_configuration.py new file mode 100644 index 00000000..bbc9b1f1 --- /dev/null +++ b/mcp_server/tests/test_neptune_configuration.py @@ -0,0 +1,308 @@ +#!/usr/bin/env python3 +""" +Tests for Neptune database provider configuration and validation. + +These tests validate Neptune-specific configuration requirements including: +- Endpoint format validation (neptune-db:// and neptune-graph://) +- AOSS host requirement validation +- AWS credential validation (mocked) +- Environment variable overrides +- Factory creation with Neptune provider +""" + +import os +import sys +from pathlib import Path +from unittest.mock import MagicMock, patch + +from config.schema import DatabaseProvidersConfig, GraphitiConfig, NeptuneProviderConfig +from services.factories import DatabaseDriverFactory + + +def test_neptune_provider_config_validation(): + """Test NeptuneProviderConfig validation rules.""" + print('\nTesting Neptune provider configuration validation...') + + # Test valid Database endpoint + try: + config = NeptuneProviderConfig( + host='neptune-db://my-cluster.us-east-1.neptune.amazonaws.com', + aoss_host='my-aoss.us-east-1.aoss.amazonaws.com', + port=8182, + aoss_port=443, + ) + print('✓ Valid Database endpoint accepted') + assert config.host.startswith('neptune-db://') + except Exception as e: + print(f'✗ Failed to accept valid Database endpoint: {e}') + raise + + # Test valid Analytics endpoint + try: + config = NeptuneProviderConfig( + host='neptune-graph://g-abc123xyz', + aoss_host='my-aoss.us-east-1.aoss.amazonaws.com', + ) + print('✓ Valid Analytics endpoint accepted') + assert config.host.startswith('neptune-graph://') + except Exception as e: + print(f'✗ Failed to accept valid Analytics endpoint: {e}') + raise + + # Test invalid endpoint format + try: + config = NeptuneProviderConfig( + host='https://my-neptune.com', + aoss_host='my-aoss.us-east-1.aoss.amazonaws.com', + ) + print('✗ Invalid endpoint format should have been rejected') + raise AssertionError('Expected ValueError for invalid endpoint format') + except ValueError as e: + print(f'✓ Invalid endpoint format rejected: {str(e)[:60]}...') + assert 'must start with neptune-db:// or neptune-graph://' in str(e) + + # Test missing AOSS host + try: + config = NeptuneProviderConfig( + host='neptune-db://my-cluster.us-east-1.neptune.amazonaws.com', + aoss_host=None, + ) + print('✗ Missing AOSS host should have been rejected') + raise AssertionError('Expected ValueError for missing AOSS host') + except ValueError as e: + print(f'✓ Missing AOSS host rejected: {str(e)[:60]}...') + assert 'requires aoss_host' in str(e) + + # Test port range validation + try: + config = NeptuneProviderConfig( + host='neptune-db://my-cluster.us-east-1.neptune.amazonaws.com', + aoss_host='my-aoss.us-east-1.aoss.amazonaws.com', + port=70000, # Invalid port + ) + print('✗ Invalid port should have been rejected') + raise AssertionError('Expected ValidationError for invalid port') + except Exception as e: + print(f'✓ Invalid port rejected: {str(e)[:60]}...') + + print('✓ Neptune provider configuration validation complete') + + +def test_neptune_environment_overrides(): + """Test Neptune configuration with environment variable overrides.""" + print('\nTesting Neptune environment variable overrides...') + + # Set Neptune environment variables + test_env = { + 'NEPTUNE_HOST': 'neptune-db://test-cluster.us-west-2.neptune.amazonaws.com', + 'AOSS_HOST': 'test-aoss.us-west-2.aoss.amazonaws.com', + 'NEPTUNE_PORT': '9999', + 'AOSS_PORT': '9443', + 'AWS_REGION': 'us-west-2', + } + + with patch.dict(os.environ, test_env, clear=False): + try: + # Load config with environment overrides + config_path = Path(__file__).parent.parent / 'config' / 'config.yaml' + config = GraphitiConfig(_env_file=None, config_path=str(config_path)) + + print(f'✓ Loaded configuration with environment overrides') + + # Verify environment variables were applied + if config.database.providers and config.database.providers.neptune: + neptune_config = config.database.providers.neptune + print( + f' Neptune host: {neptune_config.host}' + ) + print( + f' AOSS host: {neptune_config.aoss_host}' + ) + print(f' Neptune port: {neptune_config.port}') + print(f' AOSS port: {neptune_config.aoss_port}') + print(f' Region: {neptune_config.region}') + + # Verify the overrides were applied correctly + assert neptune_config.host == test_env['NEPTUNE_HOST'] + assert neptune_config.aoss_host == test_env['AOSS_HOST'] + assert neptune_config.port == 9999 + assert neptune_config.aoss_port == 9443 + assert neptune_config.region == test_env['AWS_REGION'] + print('✓ All environment overrides applied correctly') + else: + print('⚠ Neptune provider not configured, skipping validation') + + except Exception as e: + print(f'✗ Failed to load configuration with environment overrides: {e}') + raise + + print('✓ Neptune environment override tests complete') + + +def test_neptune_factory_creation_with_mock_credentials(): + """Test Neptune factory creation with mocked AWS credentials.""" + print('\nTesting Neptune factory creation with mocked credentials...') + + # Mock AWS credentials + mock_credentials = MagicMock() + mock_credentials.access_key = 'mock_access_key' + mock_credentials.secret_key = 'mock_secret_key' + mock_credentials.token = None + + mock_session = MagicMock() + mock_session.get_credentials.return_value = mock_credentials + mock_session.region_name = 'us-east-1' + + # Create test configuration + test_config = { + 'database': { + 'provider': 'neptune', + 'providers': { + 'neptune': { + 'host': 'neptune-db://test-cluster.us-east-1.neptune.amazonaws.com', + 'aoss_host': 'test-aoss.us-east-1.aoss.amazonaws.com', + 'port': 8182, + 'aoss_port': 443, + 'region': 'us-east-1', + } + }, + } + } + + with patch('boto3.Session', return_value=mock_session): + try: + # Create database config using factory + config = DatabaseProvidersConfig(**test_config['database']['providers']) + print('✓ Created DatabaseProvidersConfig with Neptune') + + # Verify Neptune config was created + assert config.neptune is not None + print('✓ Neptune provider config exists') + + # Create driver config from factory + db_config = DatabaseDriverFactory.create_config(test_config) + print('✓ Created driver config from factory') + + # Verify config contains expected Neptune parameters + assert db_config['driver'] == 'neptune' + assert db_config['host'] == 'neptune-db://test-cluster.us-east-1.neptune.amazonaws.com' + assert db_config['aoss_host'] == 'test-aoss.us-east-1.aoss.amazonaws.com' + assert db_config['port'] == 8182 + assert db_config['aoss_port'] == 443 + assert db_config['region'] == 'us-east-1' + print('✓ All Neptune parameters validated correctly') + + except Exception as e: + print(f'✗ Factory creation failed: {e}') + raise + + print('✓ Neptune factory creation tests complete') + + +def test_neptune_factory_missing_credentials(): + """Test Neptune factory creation fails gracefully without AWS credentials.""" + print('\nTesting Neptune factory behavior with missing AWS credentials...') + + # Mock AWS session with no credentials + mock_session = MagicMock() + mock_session.get_credentials.return_value = None + mock_session.region_name = 'us-east-1' + + test_config = { + 'database': { + 'provider': 'neptune', + 'providers': { + 'neptune': { + 'host': 'neptune-db://test-cluster.us-east-1.neptune.amazonaws.com', + 'aoss_host': 'test-aoss.us-east-1.aoss.amazonaws.com', + 'port': 8182, + 'aoss_port': 443, + } + }, + } + } + + with patch('boto3.Session', return_value=mock_session): + try: + db_config = DatabaseDriverFactory.create_config(test_config) + print('✗ Factory should have failed with missing credentials') + raise AssertionError('Expected ValueError for missing AWS credentials') + except ValueError as e: + print(f'✓ Missing credentials rejected: {str(e)[:60]}...') + assert 'AWS credentials not configured' in str(e) + assert 'aws configure' in str(e).lower() + + print('✓ Missing credentials handling validated') + + +def test_neptune_factory_import_check(): + """Test Neptune factory import checking and error messages.""" + print('\nTesting Neptune driver import availability...') + + try: + from graphiti_core.driver.neptune_driver import NeptuneDriver + + print('✓ NeptuneDriver successfully imported') + print(f' NeptuneDriver class: {NeptuneDriver.__name__}') + + except ImportError as e: + print(f'⚠ NeptuneDriver not available: {e}') + print(' This is expected if graphiti-core[neptune] is not installed') + print(' Install with: uv add graphiti-core[neptune]') + + print('✓ Import check complete') + + +def test_database_providers_config_with_neptune(): + """Test DatabaseProvidersConfig accepts Neptune configuration.""" + print('\nTesting DatabaseProvidersConfig with Neptune...') + + try: + config = DatabaseProvidersConfig( + neptune=NeptuneProviderConfig( + host='neptune-db://my-cluster.us-east-1.neptune.amazonaws.com', + aoss_host='my-aoss.us-east-1.aoss.amazonaws.com', + port=8182, + aoss_port=443, + region='us-east-1', + ) + ) + print('✓ DatabaseProvidersConfig created with Neptune') + + assert config.neptune is not None + assert config.neptune.host == 'neptune-db://my-cluster.us-east-1.neptune.amazonaws.com' + assert config.neptune.aoss_host == 'my-aoss.us-east-1.aoss.amazonaws.com' + assert config.neptune.port == 8182 + assert config.neptune.aoss_port == 443 + assert config.neptune.region == 'us-east-1' + print('✓ All Neptune fields validated correctly') + + except Exception as e: + print(f'✗ Failed to create DatabaseProvidersConfig with Neptune: {e}') + raise + + print('✓ DatabaseProvidersConfig Neptune integration complete') + + +if __name__ == '__main__': + print('=' * 70) + print('Neptune Configuration Tests') + print('=' * 70) + + try: + test_neptune_provider_config_validation() + test_neptune_environment_overrides() + test_database_providers_config_with_neptune() + test_neptune_factory_import_check() + test_neptune_factory_creation_with_mock_credentials() + test_neptune_factory_missing_credentials() + + print('\n' + '=' * 70) + print('All Neptune tests passed!') + print('=' * 70) + + except Exception as e: + print('\n' + '=' * 70) + print(f'Tests failed: {e}') + print('=' * 70) + raise diff --git a/mcp_server/tests/test_neptune_simple.py b/mcp_server/tests/test_neptune_simple.py new file mode 100644 index 00000000..a4c19791 --- /dev/null +++ b/mcp_server/tests/test_neptune_simple.py @@ -0,0 +1,225 @@ +#!/usr/bin/env python3 +""" +Simple Neptune validation tests that can run with minimal dependencies. + +These tests verify core Neptune configuration logic without requiring +full MCP server dependencies. +""" + + +def test_neptune_endpoint_validation(): + """Test Neptune endpoint format validation logic.""" + print('\nTesting Neptune endpoint format validation...') + + valid_database_endpoints = [ + 'neptune-db://my-cluster.us-east-1.neptune.amazonaws.com', + 'neptune-db://cluster.region.neptune.amazonaws.com', + 'neptune-db://localhost', + ] + + valid_analytics_endpoints = [ + 'neptune-graph://g-abc123xyz', + 'neptune-graph://g-12345', + ] + + invalid_endpoints = [ + 'https://neptune.com', + 'http://localhost', + 'neptune://wrong-prefix', + 'bolt://localhost', + 'redis://localhost', + ] + + # Test valid Database endpoints + for endpoint in valid_database_endpoints: + is_valid = endpoint.startswith('neptune-db://') + assert is_valid, f'Expected {endpoint} to be valid Database endpoint' + print(f'✓ Valid Database endpoint: {endpoint}') + + # Test valid Analytics endpoints + for endpoint in valid_analytics_endpoints: + is_valid = endpoint.startswith('neptune-graph://') + assert is_valid, f'Expected {endpoint} to be valid Analytics endpoint' + print(f'✓ Valid Analytics endpoint: {endpoint}') + + # Test invalid endpoints + for endpoint in invalid_endpoints: + is_valid = endpoint.startswith(('neptune-db://', 'neptune-graph://')) + assert not is_valid, f'Expected {endpoint} to be invalid' + print(f'✓ Rejected invalid endpoint: {endpoint}') + + print('✓ Neptune endpoint validation logic verified') + + +def test_neptune_port_ranges(): + """Test Neptune port validation logic.""" + print('\nTesting Neptune port validation...') + + valid_ports = [1, 8182, 9999, 443, 65535] + invalid_ports = [0, -1, 70000, 100000] + + # Test valid ports + for port in valid_ports: + is_valid = 1 <= port <= 65535 + assert is_valid, f'Expected {port} to be valid' + print(f'✓ Valid port: {port}') + + # Test invalid ports + for port in invalid_ports: + is_valid = 1 <= port <= 65535 + assert not is_valid, f'Expected {port} to be invalid' + print(f'✓ Rejected invalid port: {port}') + + print('✓ Neptune port validation logic verified') + + +def test_neptune_configuration_requirements(): + """Test Neptune configuration requirements.""" + print('\nTesting Neptune configuration requirements...') + + # Neptune requires both graph endpoint and AOSS endpoint + required_fields = ['host', 'aoss_host', 'port', 'aoss_port'] + + print('Neptune requires the following configuration fields:') + for field in required_fields: + print(f' - {field}') + + # Verify required fields are documented + assert 'host' in required_fields + assert 'aoss_host' in required_fields + assert 'port' in required_fields + assert 'aoss_port' in required_fields + + print('✓ All required Neptune fields documented') + + # Verify default values are sensible + defaults = { + 'host': 'neptune-db://localhost', + 'port': 8182, + 'aoss_port': 443, + } + + print('\nDefault values:') + for field, value in defaults.items(): + print(f' - {field}: {value}') + + assert defaults['port'] == 8182 # Standard Neptune port + assert defaults['aoss_port'] == 443 # Standard HTTPS port for AOSS + + print('✓ Neptune configuration requirements verified') + + +def test_neptune_error_messages(): + """Test Neptune error message quality.""" + print('\nTesting Neptune error message quality...') + + # Error messages should be helpful and actionable + error_scenarios = { + 'invalid_endpoint': 'host must start with neptune-db:// or neptune-graph://', + 'missing_aoss': 'requires aoss_host', + 'missing_credentials': 'AWS credentials not configured', + 'setup_help': 'aws configure', + } + + print('Expected error message content:') + for scenario, expected in error_scenarios.items(): + print(f' - {scenario}: "{expected}"') + + # Verify error messages are informative + assert len(error_scenarios) > 0 + assert all(len(msg) > 10 for msg in error_scenarios.values()) + + print('✓ Error message content verified') + + +def test_neptune_aws_integration(): + """Test Neptune AWS integration requirements.""" + print('\nTesting Neptune AWS integration requirements...') + + # Neptune requires AWS credentials + aws_credential_sources = [ + 'AWS CLI (aws configure)', + 'Environment variables (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY)', + 'IAM role (when running on AWS)', + 'Credentials file (~/.aws/credentials)', + ] + + print('Neptune supports the following AWS credential sources:') + for source in aws_credential_sources: + print(f' - {source}') + + assert len(aws_credential_sources) >= 4 + print('✓ AWS credential sources documented') + + # Neptune requires AWS region + print('\nNeptune requires AWS region configuration') + region_sources = [ + 'config.yaml (region field)', + 'AWS_REGION environment variable', + 'AWS profile default region', + ] + + for source in region_sources: + print(f' - {source}') + + assert len(region_sources) >= 3 + print('✓ Region configuration sources documented') + + +def test_neptune_dependencies(): + """Test Neptune dependency requirements.""" + print('\nTesting Neptune dependency requirements...') + + # Neptune requires specific Python packages + required_packages = [ + 'boto3>=1.39.16', + 'opensearch-py>=3.0.0', + 'langchain-aws>=0.2.29', + ] + + print('Neptune requires the following Python packages:') + for package in required_packages: + print(f' - {package}') + + assert len(required_packages) >= 3 + print('✓ Dependency requirements documented') + + # Installation methods + install_commands = [ + 'pip install graphiti-core[neptune]', + 'uv add graphiti-core[neptune]', + ] + + print('\nInstallation commands:') + for cmd in install_commands: + print(f' - {cmd}') + + assert len(install_commands) >= 2 + print('✓ Installation methods documented') + + +if __name__ == '__main__': + print('=' * 70) + print('Neptune Simple Validation Tests') + print('=' * 70) + + try: + test_neptune_endpoint_validation() + test_neptune_port_ranges() + test_neptune_configuration_requirements() + test_neptune_error_messages() + test_neptune_aws_integration() + test_neptune_dependencies() + + print('\n' + '=' * 70) + print('All simple validation tests passed!') + print('=' * 70) + print('\nNote: For full integration tests, run:') + print(' python tests/test_neptune_configuration.py') + print('=' * 70) + + except AssertionError as e: + print('\n' + '=' * 70) + print(f'Test failed: {e}') + print('=' * 70) + raise diff --git a/mcp_server/uv.lock b/mcp_server/uv.lock index 3cf9af91..aabe89b9 100644 --- a/mcp_server/uv.lock +++ b/mcp_server/uv.lock @@ -233,6 +233,34 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a0/59/76ab57e3fe74484f48a53f8e337171b4a2349e506eabe136d7e01d059086/backports_asyncio_runner-1.2.0-py3-none-any.whl", hash = "sha256:0da0a936a8aeb554eccb426dc55af3ba63bcdc69fa1a600b5bb305413a4477b5", size = 12313, upload-time = "2025-07-02T02:27:14.263Z" }, ] +[[package]] +name = "boto3" +version = "1.41.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "botocore" }, + { name = "jmespath" }, + { name = "s3transfer" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fa/81/2600e83ddd7cb1dac43d28fd39774434afcda0d85d730402192b1a9266a3/boto3-1.41.2.tar.gz", hash = "sha256:7054fbc61cadab383f40ea6d725013ba6c8f569641dddb14c0055e790280ad6c", size = 111593, upload-time = "2025-11-21T20:32:08.622Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/48/41/1ed7fdc3f124c1cf2df78e605588fa78a182410b832f5b71944a69436171/boto3-1.41.2-py3-none-any.whl", hash = "sha256:edcde82fdae4201aa690e3683f8e5b1a846cf1bbf79d03db4fa8a2f6f46dba9c", size = 139343, upload-time = "2025-11-21T20:32:07.147Z" }, +] + +[[package]] +name = "botocore" +version = "1.41.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jmespath" }, + { name = "python-dateutil" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c5/0b/6eb5dc752b240dd0b76d7e3257ae25b70683896d1789e7bfb78fba7c7c99/botocore-1.41.2.tar.gz", hash = "sha256:49a3e8f4c1a1759a687941fef8b36efd7bafcf63c1ef74aa75d6497eb4887c9c", size = 14660558, upload-time = "2025-11-21T20:31:58.785Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/77/4d/516ee2157c0686fbe48ca8b94dffc17a0c35040d4626761d74b1a43215c8/botocore-1.41.2-py3-none-any.whl", hash = "sha256:154052dfaa7292212f01c8fab822c76cd10a15a7e164e4c45e4634eb40214b90", size = 14324839, upload-time = "2025-11-21T20:31:56.236Z" }, +] + [[package]] name = "cachetools" version = "5.5.2" @@ -455,6 +483,14 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/12/b3/231ffd4ab1fc9d679809f356cebee130ac7daa00d6d6f3206dd4fd137e9e/distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2", size = 20277, upload-time = "2023-12-24T09:54:30.421Z" }, ] +[[package]] +name = "events" +version = "0.5" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/25/ed/e47dec0626edd468c84c04d97769e7ab4ea6457b7f54dcb3f72b17fcd876/Events-0.5-py3-none-any.whl", hash = "sha256:a7286af378ba3e46640ac9825156c93bdba7502174dd696090fdfcd4d80a1abd", size = 6758, upload-time = "2023-07-31T08:23:13.645Z" }, +] + [[package]] name = "exceptiongroup" version = "1.3.0" @@ -648,7 +684,7 @@ wheels = [ [[package]] name = "graphiti-core" -version = "0.23.1" +version = "0.24.1" source = { editable = "../" } dependencies = [ { name = "diskcache" }, @@ -665,6 +701,12 @@ dependencies = [ falkordb = [ { name = "falkordb" }, ] +neptune = [ + { name = "boto3" }, + { name = "langchain-aws", version = "0.2.35", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" }, + { name = "langchain-aws", version = "1.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12'" }, + { name = "opensearch-py" }, +] [package.metadata] requires-dist = [ @@ -734,6 +776,67 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ab/f8/14672d69a91495f43462c5490067eeafc30346e81bda1a62848e897f9bc3/groq-0.31.0-py3-none-any.whl", hash = "sha256:5e3c7ec9728b7cccf913da982a9b5ebb46dc18a070b35e12a3d6a1e12d6b0f7f", size = 131365, upload-time = "2025-08-05T23:13:59.768Z" }, ] +[[package]] +name = "grpcio" +version = "1.76.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b6/e0/318c1ce3ae5a17894d5791e87aea147587c9e702f24122cc7a5c8bbaeeb1/grpcio-1.76.0.tar.gz", hash = "sha256:7be78388d6da1a25c0d5ec506523db58b18be22d9c37d8d3a32c08be4987bd73", size = 12785182, upload-time = "2025-10-21T16:23:12.106Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/88/17/ff4795dc9a34b6aee6ec379f1b66438a3789cd1315aac0cbab60d92f74b3/grpcio-1.76.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:65a20de41e85648e00305c1bb09a3598f840422e522277641145a32d42dcefcc", size = 5840037, upload-time = "2025-10-21T16:20:25.069Z" }, + { url = "https://files.pythonhosted.org/packages/4e/ff/35f9b96e3fa2f12e1dcd58a4513a2e2294a001d64dec81677361b7040c9a/grpcio-1.76.0-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:40ad3afe81676fd9ec6d9d406eda00933f218038433980aa19d401490e46ecde", size = 11836482, upload-time = "2025-10-21T16:20:30.113Z" }, + { url = "https://files.pythonhosted.org/packages/3e/1c/8374990f9545e99462caacea5413ed783014b3b66ace49e35c533f07507b/grpcio-1.76.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:035d90bc79eaa4bed83f524331d55e35820725c9fbb00ffa1904d5550ed7ede3", size = 6407178, upload-time = "2025-10-21T16:20:32.733Z" }, + { url = "https://files.pythonhosted.org/packages/1e/77/36fd7d7c75a6c12542c90a6d647a27935a1ecaad03e0ffdb7c42db6b04d2/grpcio-1.76.0-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:4215d3a102bd95e2e11b5395c78562967959824156af11fa93d18fdd18050990", size = 7075684, upload-time = "2025-10-21T16:20:35.435Z" }, + { url = "https://files.pythonhosted.org/packages/38/f7/e3cdb252492278e004722306c5a8935eae91e64ea11f0af3437a7de2e2b7/grpcio-1.76.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:49ce47231818806067aea3324d4bf13825b658ad662d3b25fada0bdad9b8a6af", size = 6611133, upload-time = "2025-10-21T16:20:37.541Z" }, + { url = "https://files.pythonhosted.org/packages/7e/20/340db7af162ccd20a0893b5f3c4a5d676af7b71105517e62279b5b61d95a/grpcio-1.76.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:8cc3309d8e08fd79089e13ed4819d0af72aa935dd8f435a195fd152796752ff2", size = 7195507, upload-time = "2025-10-21T16:20:39.643Z" }, + { url = "https://files.pythonhosted.org/packages/10/f0/b2160addc1487bd8fa4810857a27132fb4ce35c1b330c2f3ac45d697b106/grpcio-1.76.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:971fd5a1d6e62e00d945423a567e42eb1fa678ba89072832185ca836a94daaa6", size = 8160651, upload-time = "2025-10-21T16:20:42.492Z" }, + { url = "https://files.pythonhosted.org/packages/2c/2c/ac6f98aa113c6ef111b3f347854e99ebb7fb9d8f7bb3af1491d438f62af4/grpcio-1.76.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:9d9adda641db7207e800a7f089068f6f645959f2df27e870ee81d44701dd9db3", size = 7620568, upload-time = "2025-10-21T16:20:45.995Z" }, + { url = "https://files.pythonhosted.org/packages/90/84/7852f7e087285e3ac17a2703bc4129fafee52d77c6c82af97d905566857e/grpcio-1.76.0-cp310-cp310-win32.whl", hash = "sha256:063065249d9e7e0782d03d2bca50787f53bd0fb89a67de9a7b521c4a01f1989b", size = 3998879, upload-time = "2025-10-21T16:20:48.592Z" }, + { url = "https://files.pythonhosted.org/packages/10/30/d3d2adcbb6dd3ff59d6ac3df6ef830e02b437fb5c90990429fd180e52f30/grpcio-1.76.0-cp310-cp310-win_amd64.whl", hash = "sha256:a6ae758eb08088d36812dd5d9af7a9859c05b1e0f714470ea243694b49278e7b", size = 4706892, upload-time = "2025-10-21T16:20:50.697Z" }, + { url = "https://files.pythonhosted.org/packages/a0/00/8163a1beeb6971f66b4bbe6ac9457b97948beba8dd2fc8e1281dce7f79ec/grpcio-1.76.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:2e1743fbd7f5fa713a1b0a8ac8ebabf0ec980b5d8809ec358d488e273b9cf02a", size = 5843567, upload-time = "2025-10-21T16:20:52.829Z" }, + { url = "https://files.pythonhosted.org/packages/10/c1/934202f5cf335e6d852530ce14ddb0fef21be612ba9ecbbcbd4d748ca32d/grpcio-1.76.0-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:a8c2cf1209497cf659a667d7dea88985e834c24b7c3b605e6254cbb5076d985c", size = 11848017, upload-time = "2025-10-21T16:20:56.705Z" }, + { url = "https://files.pythonhosted.org/packages/11/0b/8dec16b1863d74af6eb3543928600ec2195af49ca58b16334972f6775663/grpcio-1.76.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:08caea849a9d3c71a542827d6df9d5a69067b0a1efbea8a855633ff5d9571465", size = 6412027, upload-time = "2025-10-21T16:20:59.3Z" }, + { url = "https://files.pythonhosted.org/packages/d7/64/7b9e6e7ab910bea9d46f2c090380bab274a0b91fb0a2fe9b0cd399fffa12/grpcio-1.76.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:f0e34c2079d47ae9f6188211db9e777c619a21d4faba6977774e8fa43b085e48", size = 7075913, upload-time = "2025-10-21T16:21:01.645Z" }, + { url = "https://files.pythonhosted.org/packages/68/86/093c46e9546073cefa789bd76d44c5cb2abc824ca62af0c18be590ff13ba/grpcio-1.76.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8843114c0cfce61b40ad48df65abcfc00d4dba82eae8718fab5352390848c5da", size = 6615417, upload-time = "2025-10-21T16:21:03.844Z" }, + { url = "https://files.pythonhosted.org/packages/f7/b6/5709a3a68500a9c03da6fb71740dcdd5ef245e39266461a03f31a57036d8/grpcio-1.76.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8eddfb4d203a237da6f3cc8a540dad0517d274b5a1e9e636fd8d2c79b5c1d397", size = 7199683, upload-time = "2025-10-21T16:21:06.195Z" }, + { url = "https://files.pythonhosted.org/packages/91/d3/4b1f2bf16ed52ce0b508161df3a2d186e4935379a159a834cb4a7d687429/grpcio-1.76.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:32483fe2aab2c3794101c2a159070584e5db11d0aa091b2c0ea9c4fc43d0d749", size = 8163109, upload-time = "2025-10-21T16:21:08.498Z" }, + { url = "https://files.pythonhosted.org/packages/5c/61/d9043f95f5f4cf085ac5dd6137b469d41befb04bd80280952ffa2a4c3f12/grpcio-1.76.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:dcfe41187da8992c5f40aa8c5ec086fa3672834d2be57a32384c08d5a05b4c00", size = 7626676, upload-time = "2025-10-21T16:21:10.693Z" }, + { url = "https://files.pythonhosted.org/packages/36/95/fd9a5152ca02d8881e4dd419cdd790e11805979f499a2e5b96488b85cf27/grpcio-1.76.0-cp311-cp311-win32.whl", hash = "sha256:2107b0c024d1b35f4083f11245c0e23846ae64d02f40b2b226684840260ed054", size = 3997688, upload-time = "2025-10-21T16:21:12.746Z" }, + { url = "https://files.pythonhosted.org/packages/60/9c/5c359c8d4c9176cfa3c61ecd4efe5affe1f38d9bae81e81ac7186b4c9cc8/grpcio-1.76.0-cp311-cp311-win_amd64.whl", hash = "sha256:522175aba7af9113c48ec10cc471b9b9bd4f6ceb36aeb4544a8e2c80ed9d252d", size = 4709315, upload-time = "2025-10-21T16:21:15.26Z" }, + { url = "https://files.pythonhosted.org/packages/bf/05/8e29121994b8d959ffa0afd28996d452f291b48cfc0875619de0bde2c50c/grpcio-1.76.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:81fd9652b37b36f16138611c7e884eb82e0cec137c40d3ef7c3f9b3ed00f6ed8", size = 5799718, upload-time = "2025-10-21T16:21:17.939Z" }, + { url = "https://files.pythonhosted.org/packages/d9/75/11d0e66b3cdf998c996489581bdad8900db79ebd83513e45c19548f1cba4/grpcio-1.76.0-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:04bbe1bfe3a68bbfd4e52402ab7d4eb59d72d02647ae2042204326cf4bbad280", size = 11825627, upload-time = "2025-10-21T16:21:20.466Z" }, + { url = "https://files.pythonhosted.org/packages/28/50/2f0aa0498bc188048f5d9504dcc5c2c24f2eb1a9337cd0fa09a61a2e75f0/grpcio-1.76.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d388087771c837cdb6515539f43b9d4bf0b0f23593a24054ac16f7a960be16f4", size = 6359167, upload-time = "2025-10-21T16:21:23.122Z" }, + { url = "https://files.pythonhosted.org/packages/66/e5/bbf0bb97d29ede1d59d6588af40018cfc345b17ce979b7b45424628dc8bb/grpcio-1.76.0-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:9f8f757bebaaea112c00dba718fc0d3260052ce714e25804a03f93f5d1c6cc11", size = 7044267, upload-time = "2025-10-21T16:21:25.995Z" }, + { url = "https://files.pythonhosted.org/packages/f5/86/f6ec2164f743d9609691115ae8ece098c76b894ebe4f7c94a655c6b03e98/grpcio-1.76.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:980a846182ce88c4f2f7e2c22c56aefd515daeb36149d1c897f83cf57999e0b6", size = 6573963, upload-time = "2025-10-21T16:21:28.631Z" }, + { url = "https://files.pythonhosted.org/packages/60/bc/8d9d0d8505feccfdf38a766d262c71e73639c165b311c9457208b56d92ae/grpcio-1.76.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f92f88e6c033db65a5ae3d97905c8fea9c725b63e28d5a75cb73b49bda5024d8", size = 7164484, upload-time = "2025-10-21T16:21:30.837Z" }, + { url = "https://files.pythonhosted.org/packages/67/e6/5d6c2fc10b95edf6df9b8f19cf10a34263b7fd48493936fffd5085521292/grpcio-1.76.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4baf3cbe2f0be3289eb68ac8ae771156971848bb8aaff60bad42005539431980", size = 8127777, upload-time = "2025-10-21T16:21:33.577Z" }, + { url = "https://files.pythonhosted.org/packages/3f/c8/dce8ff21c86abe025efe304d9e31fdb0deaaa3b502b6a78141080f206da0/grpcio-1.76.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:615ba64c208aaceb5ec83bfdce7728b80bfeb8be97562944836a7a0a9647d882", size = 7594014, upload-time = "2025-10-21T16:21:41.882Z" }, + { url = "https://files.pythonhosted.org/packages/e0/42/ad28191ebf983a5d0ecef90bab66baa5a6b18f2bfdef9d0a63b1973d9f75/grpcio-1.76.0-cp312-cp312-win32.whl", hash = "sha256:45d59a649a82df5718fd9527ce775fd66d1af35e6d31abdcdc906a49c6822958", size = 3984750, upload-time = "2025-10-21T16:21:44.006Z" }, + { url = "https://files.pythonhosted.org/packages/9e/00/7bd478cbb851c04a48baccaa49b75abaa8e4122f7d86da797500cccdd771/grpcio-1.76.0-cp312-cp312-win_amd64.whl", hash = "sha256:c088e7a90b6017307f423efbb9d1ba97a22aa2170876223f9709e9d1de0b5347", size = 4704003, upload-time = "2025-10-21T16:21:46.244Z" }, + { url = "https://files.pythonhosted.org/packages/fc/ed/71467ab770effc9e8cef5f2e7388beb2be26ed642d567697bb103a790c72/grpcio-1.76.0-cp313-cp313-linux_armv7l.whl", hash = "sha256:26ef06c73eb53267c2b319f43e6634c7556ea37672029241a056629af27c10e2", size = 5807716, upload-time = "2025-10-21T16:21:48.475Z" }, + { url = "https://files.pythonhosted.org/packages/2c/85/c6ed56f9817fab03fa8a111ca91469941fb514e3e3ce6d793cb8f1e1347b/grpcio-1.76.0-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:45e0111e73f43f735d70786557dc38141185072d7ff8dc1829d6a77ac1471468", size = 11821522, upload-time = "2025-10-21T16:21:51.142Z" }, + { url = "https://files.pythonhosted.org/packages/ac/31/2b8a235ab40c39cbc141ef647f8a6eb7b0028f023015a4842933bc0d6831/grpcio-1.76.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:83d57312a58dcfe2a3a0f9d1389b299438909a02db60e2f2ea2ae2d8034909d3", size = 6362558, upload-time = "2025-10-21T16:21:54.213Z" }, + { url = "https://files.pythonhosted.org/packages/bd/64/9784eab483358e08847498ee56faf8ff6ea8e0a4592568d9f68edc97e9e9/grpcio-1.76.0-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:3e2a27c89eb9ac3d81ec8835e12414d73536c6e620355d65102503064a4ed6eb", size = 7049990, upload-time = "2025-10-21T16:21:56.476Z" }, + { url = "https://files.pythonhosted.org/packages/2b/94/8c12319a6369434e7a184b987e8e9f3b49a114c489b8315f029e24de4837/grpcio-1.76.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:61f69297cba3950a524f61c7c8ee12e55c486cb5f7db47ff9dcee33da6f0d3ae", size = 6575387, upload-time = "2025-10-21T16:21:59.051Z" }, + { url = "https://files.pythonhosted.org/packages/15/0f/f12c32b03f731f4a6242f771f63039df182c8b8e2cf8075b245b409259d4/grpcio-1.76.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6a15c17af8839b6801d554263c546c69c4d7718ad4321e3166175b37eaacca77", size = 7166668, upload-time = "2025-10-21T16:22:02.049Z" }, + { url = "https://files.pythonhosted.org/packages/ff/2d/3ec9ce0c2b1d92dd59d1c3264aaec9f0f7c817d6e8ac683b97198a36ed5a/grpcio-1.76.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:25a18e9810fbc7e7f03ec2516addc116a957f8cbb8cbc95ccc80faa072743d03", size = 8124928, upload-time = "2025-10-21T16:22:04.984Z" }, + { url = "https://files.pythonhosted.org/packages/1a/74/fd3317be5672f4856bcdd1a9e7b5e17554692d3db9a3b273879dc02d657d/grpcio-1.76.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:931091142fd8cc14edccc0845a79248bc155425eee9a98b2db2ea4f00a235a42", size = 7589983, upload-time = "2025-10-21T16:22:07.881Z" }, + { url = "https://files.pythonhosted.org/packages/45/bb/ca038cf420f405971f19821c8c15bcbc875505f6ffadafe9ffd77871dc4c/grpcio-1.76.0-cp313-cp313-win32.whl", hash = "sha256:5e8571632780e08526f118f74170ad8d50fb0a48c23a746bef2a6ebade3abd6f", size = 3984727, upload-time = "2025-10-21T16:22:10.032Z" }, + { url = "https://files.pythonhosted.org/packages/41/80/84087dc56437ced7cdd4b13d7875e7439a52a261e3ab4e06488ba6173b0a/grpcio-1.76.0-cp313-cp313-win_amd64.whl", hash = "sha256:f9f7bd5faab55f47231ad8dba7787866b69f5e93bc306e3915606779bbfb4ba8", size = 4702799, upload-time = "2025-10-21T16:22:12.709Z" }, + { url = "https://files.pythonhosted.org/packages/b4/46/39adac80de49d678e6e073b70204091e76631e03e94928b9ea4ecf0f6e0e/grpcio-1.76.0-cp314-cp314-linux_armv7l.whl", hash = "sha256:ff8a59ea85a1f2191a0ffcc61298c571bc566332f82e5f5be1b83c9d8e668a62", size = 5808417, upload-time = "2025-10-21T16:22:15.02Z" }, + { url = "https://files.pythonhosted.org/packages/9c/f5/a4531f7fb8b4e2a60b94e39d5d924469b7a6988176b3422487be61fe2998/grpcio-1.76.0-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:06c3d6b076e7b593905d04fdba6a0525711b3466f43b3400266f04ff735de0cd", size = 11828219, upload-time = "2025-10-21T16:22:17.954Z" }, + { url = "https://files.pythonhosted.org/packages/4b/1c/de55d868ed7a8bd6acc6b1d6ddc4aa36d07a9f31d33c912c804adb1b971b/grpcio-1.76.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:fd5ef5932f6475c436c4a55e4336ebbe47bd3272be04964a03d316bbf4afbcbc", size = 6367826, upload-time = "2025-10-21T16:22:20.721Z" }, + { url = "https://files.pythonhosted.org/packages/59/64/99e44c02b5adb0ad13ab3adc89cb33cb54bfa90c74770f2607eea629b86f/grpcio-1.76.0-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:b331680e46239e090f5b3cead313cc772f6caa7d0fc8de349337563125361a4a", size = 7049550, upload-time = "2025-10-21T16:22:23.637Z" }, + { url = "https://files.pythonhosted.org/packages/43/28/40a5be3f9a86949b83e7d6a2ad6011d993cbe9b6bd27bea881f61c7788b6/grpcio-1.76.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:2229ae655ec4e8999599469559e97630185fdd53ae1e8997d147b7c9b2b72cba", size = 6575564, upload-time = "2025-10-21T16:22:26.016Z" }, + { url = "https://files.pythonhosted.org/packages/4b/a9/1be18e6055b64467440208a8559afac243c66a8b904213af6f392dc2212f/grpcio-1.76.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:490fa6d203992c47c7b9e4a9d39003a0c2bcc1c9aa3c058730884bbbb0ee9f09", size = 7176236, upload-time = "2025-10-21T16:22:28.362Z" }, + { url = "https://files.pythonhosted.org/packages/0f/55/dba05d3fcc151ce6e81327541d2cc8394f442f6b350fead67401661bf041/grpcio-1.76.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:479496325ce554792dba6548fae3df31a72cef7bad71ca2e12b0e58f9b336bfc", size = 8125795, upload-time = "2025-10-21T16:22:31.075Z" }, + { url = "https://files.pythonhosted.org/packages/4a/45/122df922d05655f63930cf42c9e3f72ba20aadb26c100ee105cad4ce4257/grpcio-1.76.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:1c9b93f79f48b03ada57ea24725d83a30284a012ec27eab2cf7e50a550cbbbcc", size = 7592214, upload-time = "2025-10-21T16:22:33.831Z" }, + { url = "https://files.pythonhosted.org/packages/4a/6e/0b899b7f6b66e5af39e377055fb4a6675c9ee28431df5708139df2e93233/grpcio-1.76.0-cp314-cp314-win32.whl", hash = "sha256:747fa73efa9b8b1488a95d0ba1039c8e2dca0f741612d80415b1e1c560febf4e", size = 4062961, upload-time = "2025-10-21T16:22:36.468Z" }, + { url = "https://files.pythonhosted.org/packages/19/41/0b430b01a2eb38ee887f88c1f07644a1df8e289353b78e82b37ef988fb64/grpcio-1.76.0-cp314-cp314-win_amd64.whl", hash = "sha256:922fa70ba549fce362d2e2871ab542082d66e2aaf0c19480ea453905b01f384e", size = 4834462, upload-time = "2025-10-21T16:22:39.772Z" }, +] + [[package]] name = "h11" version = "0.16.0" @@ -916,6 +1019,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b3/4a/4175a563579e884192ba6e81725fc0448b042024419be8d83aa8a80a3f44/jiter-0.10.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3aa96f2abba33dc77f79b4cf791840230375f9534e5fac927ccceb58c5e604a5", size = 354213, upload-time = "2025-05-18T19:04:41.894Z" }, ] +[[package]] +name = "jmespath" +version = "1.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/00/2a/e867e8531cf3e36b41201936b7fa7ba7b5702dbef42922193f05c8976cd6/jmespath-1.0.1.tar.gz", hash = "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe", size = 25843, upload-time = "2022-06-17T18:00:12.224Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/31/b4/b9b800c45527aadd64d5b442f9b932b00648617eb5d63d2c7a6587b7cafc/jmespath-1.0.1-py3-none-any.whl", hash = "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980", size = 20256, upload-time = "2022-06-17T18:00:10.251Z" }, +] + [[package]] name = "joblib" version = "1.5.1" @@ -947,35 +1059,119 @@ wheels = [ ] [[package]] -name = "langchain-core" -version = "0.3.74" +name = "langchain-aws" +version = "0.2.35" source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "jsonpatch" }, - { name = "langsmith" }, - { name = "packaging" }, - { name = "pydantic" }, - { name = "pyyaml" }, - { name = "tenacity" }, - { name = "typing-extensions" }, +resolution-markers = [ + "python_full_version >= '3.14'", + "python_full_version == '3.12.*'", + "python_full_version == '3.13.*'", ] -sdist = { url = "https://files.pythonhosted.org/packages/f1/c6/5d755a0f1f4857abbe5ea6f5907ed0e2b5df52bf4dde0a0fd768290e3084/langchain_core-0.3.74.tar.gz", hash = "sha256:ff604441aeade942fbcc0a3860a592daba7671345230c2078ba2eb5f82b6ba76", size = 569553, upload-time = "2025-08-07T20:47:05.094Z" } +dependencies = [ + { name = "boto3", marker = "python_full_version >= '3.12'" }, + { name = "langchain-core", version = "0.3.80", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" }, + { name = "numpy", marker = "python_full_version >= '3.12'" }, + { name = "pydantic", marker = "python_full_version >= '3.12'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8d/7a/19a903725acbb1c4481dc0391b2551250bf4e04cbe5a891a55e09319772b/langchain_aws-0.2.35.tar.gz", hash = "sha256:45793a34fe45d365f4292cc768db74669ca24601d2c5da1ac6f44403750d70af", size = 120567, upload-time = "2025-10-02T23:59:57.204Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/4d/26/545283681ac0379d31c7ad0bac5f195e1982092d76c65ca048db9e3cec0e/langchain_core-0.3.74-py3-none-any.whl", hash = "sha256:088338b5bc2f6a66892f9afc777992c24ee3188f41cbc603d09181e34a228ce7", size = 443453, upload-time = "2025-08-07T20:47:03.853Z" }, + { url = "https://files.pythonhosted.org/packages/41/92/1827652b4ed6d8ffaffe8b40be49a6889a9b3cb4b523fb56871691c48601/langchain_aws-0.2.35-py3-none-any.whl", hash = "sha256:8ddb10f3c29f6d52bcbaa4d7f4f56462acf01f608adc7c70f41e5a476899a6bc", size = 145620, upload-time = "2025-10-02T23:59:55.288Z" }, +] + +[[package]] +name = "langchain-aws" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.12'", +] +dependencies = [ + { name = "boto3", marker = "python_full_version < '3.12'" }, + { name = "langchain-core", version = "1.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12'" }, + { name = "numpy", marker = "python_full_version < '3.12'" }, + { name = "pydantic", marker = "python_full_version < '3.12'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/52/1d/bb306951b1c394b7a27effb8eb6c9ee65dd77fcc4be7c20f76e3299a9e1e/langchain_aws-1.1.0.tar.gz", hash = "sha256:1e2f8570328eae4907c3cf7e900dc68d8034ddc865d9dc96823c9f9d8cccb901", size = 393899, upload-time = "2025-11-24T14:35:24.216Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/26/33/91b8d2a7570657b371382b45054142c54165a51706990a5c1b4cc40c0e9a/langchain_aws-1.1.0-py3-none-any.whl", hash = "sha256:8ec074615b42839e035354063717374c32c63f5028ef5221ba073fd5f3ef5e37", size = 152432, upload-time = "2025-11-24T14:35:23.004Z" }, +] + +[[package]] +name = "langchain-core" +version = "0.3.80" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.14'", + "python_full_version == '3.12.*'", + "python_full_version == '3.13.*'", +] +dependencies = [ + { name = "jsonpatch", marker = "python_full_version >= '3.12'" }, + { name = "langsmith", marker = "python_full_version >= '3.12'" }, + { name = "packaging", marker = "python_full_version >= '3.12'" }, + { name = "pydantic", marker = "python_full_version >= '3.12'" }, + { name = "pyyaml", marker = "python_full_version >= '3.12'" }, + { name = "tenacity", marker = "python_full_version >= '3.12'" }, + { name = "typing-extensions", marker = "python_full_version >= '3.12'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/49/49/f76647b7ba1a6f9c11b0343056ab4d3e5fc445981d205237fed882b2ad60/langchain_core-0.3.80.tar.gz", hash = "sha256:29636b82513ab49e834764d023c4d18554d3d719a185d37b019d0a8ae948c6bb", size = 583629, upload-time = "2025-11-19T22:23:18.771Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/da/e8/e7a090ebe37f2b071c64e81b99fb1273b3151ae932f560bb94c22f191cde/langchain_core-0.3.80-py3-none-any.whl", hash = "sha256:2141e3838d100d17dce2359f561ec0df52c526bae0de6d4f469f8026c5747456", size = 450786, upload-time = "2025-11-19T22:23:17.133Z" }, +] + +[[package]] +name = "langchain-core" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.12'", +] +dependencies = [ + { name = "jsonpatch", marker = "python_full_version < '3.12'" }, + { name = "langsmith", marker = "python_full_version < '3.12'" }, + { name = "packaging", marker = "python_full_version < '3.12'" }, + { name = "pydantic", marker = "python_full_version < '3.12'" }, + { name = "pyyaml", marker = "python_full_version < '3.12'" }, + { name = "tenacity", marker = "python_full_version < '3.12'" }, + { name = "typing-extensions", marker = "python_full_version < '3.12'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/1e/17/67c1cc2ace919e2b02dd9d783154d7fb3f1495a4ef835d9cd163b7855ac2/langchain_core-1.1.0.tar.gz", hash = "sha256:2b76a82d427922c8bc51c08404af4fc2a29e9f161dfe2297cb05091e810201e7", size = 781995, upload-time = "2025-11-21T21:01:26.958Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/71/1e/e129fc471a2d2a7b3804480a937b5ab9319cab9f4142624fcb115f925501/langchain_core-1.1.0-py3-none-any.whl", hash = "sha256:2c9f27dadc6d21ed4aa46506a37a56e6a7e2d2f9141922dc5c251ba921822ee6", size = 473752, upload-time = "2025-11-21T21:01:25.841Z" }, ] [[package]] name = "langchain-text-splitters" version = "0.3.9" source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.14'", + "python_full_version == '3.12.*'", + "python_full_version == '3.13.*'", +] dependencies = [ - { name = "langchain-core" }, + { name = "langchain-core", version = "0.3.80", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/91/52/d43ad77acae169210cc476cbc1e4ab37a701017c950211a11ab500fe7d7e/langchain_text_splitters-0.3.9.tar.gz", hash = "sha256:7cd1e5a3aaf609979583eeca2eb34177622570b8fa8f586a605c6b1c34e7ebdb", size = 45260, upload-time = "2025-07-24T14:38:45.14Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/e2/52/7638394b88bc15083fd2c3752a843784d9d2d110d68fed6437c8607fb749/langchain_text_splitters-0.3.9-py3-none-any.whl", hash = "sha256:cee0bb816211584ea79cc79927317c358543f40404bcfdd69e69ba3ccde54401", size = 33314, upload-time = "2025-07-24T14:38:43.953Z" }, ] +[[package]] +name = "langchain-text-splitters" +version = "1.0.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.12'", +] +dependencies = [ + { name = "langchain-core", version = "1.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fa/2e/c833dcc379c1c086453708ef5eef7d4d1f808559ca4458bd6569d5d83ad7/langchain_text_splitters-1.0.0.tar.gz", hash = "sha256:d8580a20ad7ed10b432feb273e5758b2cc0902d094919629cec0e1ad691a6744", size = 264257, upload-time = "2025-10-17T14:33:41.743Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/97/d362353ab04f865af6f81d4d46e7aa428734aa032de0017934b771fc34b7/langchain_text_splitters-1.0.0-py3-none-any.whl", hash = "sha256:f00c8219d3468f2c5bd951b708b6a7dd9bc3c62d0cfb83124c377f7170f33b2e", size = 33851, upload-time = "2025-10-17T14:33:40.46Z" }, +] + [[package]] name = "langsmith" version = "0.4.16" @@ -1074,10 +1270,10 @@ wheels = [ [[package]] name = "mcp-server" -version = "1.0.1" +version = "1.0.2" source = { virtual = "." } dependencies = [ - { name = "graphiti-core", extra = ["falkordb"] }, + { name = "graphiti-core", extra = ["falkordb", "neptune"] }, { name = "mcp" }, { name = "openai" }, { name = "pydantic-settings" }, @@ -1115,7 +1311,7 @@ requires-dist = [ { name = "anthropic", marker = "extra == 'providers'", specifier = ">=0.49.0" }, { name = "azure-identity", marker = "extra == 'azure'", specifier = ">=1.21.0" }, { name = "google-genai", marker = "extra == 'providers'", specifier = ">=1.8.0" }, - { name = "graphiti-core", extras = ["falkordb"], editable = "../" }, + { name = "graphiti-core", extras = ["falkordb", "neptune"], editable = "../" }, { name = "groq", marker = "extra == 'providers'", specifier = ">=0.2.0" }, { name = "mcp", specifier = ">=1.9.4" }, { name = "openai", specifier = ">=1.91.0" }, @@ -1514,6 +1710,35 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7a/d2/f99bdd6fc737d6b3cf0df895508d621fc9a386b375a1230ee81d46c5436e/openai-1.91.0-py3-none-any.whl", hash = "sha256:207f87aa3bc49365e014fac2f7e291b99929f4fe126c4654143440e0ad446a5f", size = 735837, upload-time = "2025-06-23T18:27:08.913Z" }, ] +[[package]] +name = "opensearch-protobufs" +version = "0.19.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "grpcio" }, + { name = "protobuf" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/16/e2/8a09dbdbfe51e30dfecb625a0f5c524a53bfa4b1fba168f73ac85621dba2/opensearch_protobufs-0.19.0-py3-none-any.whl", hash = "sha256:5137c9c2323cc7debb694754b820ca4cfb5fc8eb180c41ff125698c3ee11bfc2", size = 39778, upload-time = "2025-09-29T20:05:52.379Z" }, +] + +[[package]] +name = "opensearch-py" +version = "3.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "events" }, + { name = "opensearch-protobufs" }, + { name = "python-dateutil" }, + { name = "requests" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/65/9f/d4969f7e8fa221bfebf254cc3056e7c743ce36ac9874e06110474f7c947d/opensearch_py-3.1.0.tar.gz", hash = "sha256:883573af13175ff102b61c80b77934a9e937bdcc40cda2b92051ad53336bc055", size = 258616, upload-time = "2025-11-20T16:37:36.777Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/08/a1/293c8ad81768ad625283d960685bde07c6302abf20a685e693b48ab6eb91/opensearch_py-3.1.0-py3-none-any.whl", hash = "sha256:e5af83d0454323e6ea9ddee8c0dcc185c0181054592d23cb701da46271a3b65b", size = 385729, upload-time = "2025-11-20T16:37:34.941Z" }, +] + [[package]] name = "orjson" version = "3.11.2" @@ -1817,6 +2042,21 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/cc/35/cc0aaecf278bb4575b8555f2b137de5ab821595ddae9da9d3cd1da4072c7/propcache-0.3.2-py3-none-any.whl", hash = "sha256:98f1ec44fb675f5052cccc8e609c46ed23a35a1cfd18545ad4e29002d858a43f", size = 12663, upload-time = "2025-06-09T22:56:04.484Z" }, ] +[[package]] +name = "protobuf" +version = "6.33.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0a/03/a1440979a3f74f16cab3b75b0da1a1a7f922d56a8ddea96092391998edc0/protobuf-6.33.1.tar.gz", hash = "sha256:97f65757e8d09870de6fd973aeddb92f85435607235d20b2dfed93405d00c85b", size = 443432, upload-time = "2025-11-13T16:44:18.895Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/06/f1/446a9bbd2c60772ca36556bac8bfde40eceb28d9cc7838755bc41e001d8f/protobuf-6.33.1-cp310-abi3-win32.whl", hash = "sha256:f8d3fdbc966aaab1d05046d0240dd94d40f2a8c62856d41eaa141ff64a79de6b", size = 425593, upload-time = "2025-11-13T16:44:06.275Z" }, + { url = "https://files.pythonhosted.org/packages/a6/79/8780a378c650e3df849b73de8b13cf5412f521ca2ff9b78a45c247029440/protobuf-6.33.1-cp310-abi3-win_amd64.whl", hash = "sha256:923aa6d27a92bf44394f6abf7ea0500f38769d4b07f4be41cb52bd8b1123b9ed", size = 436883, upload-time = "2025-11-13T16:44:09.222Z" }, + { url = "https://files.pythonhosted.org/packages/cd/93/26213ff72b103ae55bb0d73e7fb91ea570ef407c3ab4fd2f1f27cac16044/protobuf-6.33.1-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:fe34575f2bdde76ac429ec7b570235bf0c788883e70aee90068e9981806f2490", size = 427522, upload-time = "2025-11-13T16:44:10.475Z" }, + { url = "https://files.pythonhosted.org/packages/c2/32/df4a35247923393aa6b887c3b3244a8c941c32a25681775f96e2b418f90e/protobuf-6.33.1-cp39-abi3-manylinux2014_aarch64.whl", hash = "sha256:f8adba2e44cde2d7618996b3fc02341f03f5bc3f2748be72dc7b063319276178", size = 324445, upload-time = "2025-11-13T16:44:11.869Z" }, + { url = "https://files.pythonhosted.org/packages/8e/d0/d796e419e2ec93d2f3fa44888861c3f88f722cde02b7c3488fcc6a166820/protobuf-6.33.1-cp39-abi3-manylinux2014_s390x.whl", hash = "sha256:0f4cf01222c0d959c2b399142deb526de420be8236f22c71356e2a544e153c53", size = 339161, upload-time = "2025-11-13T16:44:12.778Z" }, + { url = "https://files.pythonhosted.org/packages/1d/2a/3c5f05a4af06649547027d288747f68525755de692a26a7720dced3652c0/protobuf-6.33.1-cp39-abi3-manylinux2014_x86_64.whl", hash = "sha256:8fd7d5e0eb08cd5b87fd3df49bc193f5cfd778701f47e11d127d0afc6c39f1d1", size = 323171, upload-time = "2025-11-13T16:44:14.035Z" }, + { url = "https://files.pythonhosted.org/packages/08/b4/46310463b4f6ceef310f8348786f3cff181cea671578e3d9743ba61a459e/protobuf-6.33.1-py3-none-any.whl", hash = "sha256:d595a9fd694fdeb061a62fbe10eb039cc1e444df81ec9bb70c7fc59ebcb1eafa", size = 170477, upload-time = "2025-11-13T16:44:17.633Z" }, +] + [[package]] name = "psutil" version = "7.1.2" @@ -2321,6 +2561,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/24/3c/21cf283d67af33a8e6ed242396863af195a8a6134ec581524fd22b9811b6/ruff-0.12.10-py3-none-win_arm64.whl", hash = "sha256:cc138cc06ed9d4bfa9d667a65af7172b47840e1a98b02ce7011c391e54635ffc", size = 12074225, upload-time = "2025-08-21T18:23:20.137Z" }, ] +[[package]] +name = "s3transfer" +version = "0.15.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "botocore" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ca/bb/940d6af975948c1cc18f44545ffb219d3c35d78ec972b42ae229e8e37e08/s3transfer-0.15.0.tar.gz", hash = "sha256:d36fac8d0e3603eff9b5bfa4282c7ce6feb0301a633566153cbd0b93d11d8379", size = 152185, upload-time = "2025-11-20T20:28:56.327Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5f/e1/5ef25f52973aa12a19cf4e1375d00932d7fb354ffd310487ba7d44225c1a/s3transfer-0.15.0-py3-none-any.whl", hash = "sha256:6f8bf5caa31a0865c4081186689db1b2534cef721d104eb26101de4b9d6a5852", size = 85984, upload-time = "2025-11-20T20:28:55.046Z" }, +] + [[package]] name = "safetensors" version = "0.6.2" @@ -2762,7 +3014,8 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aiohttp" }, { name = "aiolimiter" }, - { name = "langchain-text-splitters" }, + { name = "langchain-text-splitters", version = "0.3.9", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" }, + { name = "langchain-text-splitters", version = "1.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12'" }, { name = "numpy", marker = "python_full_version < '3.14'" }, { name = "pillow" }, { name = "pydantic" },