contextsynapse 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- contextsynapse/__init__.py +107 -0
- contextsynapse/__main__.py +9 -0
- contextsynapse/a2a/__init__.py +28 -0
- contextsynapse/a2a/client.py +120 -0
- contextsynapse/a2a/discovery.py +128 -0
- contextsynapse/a2a/handlers.py +164 -0
- contextsynapse/a2a/models.py +246 -0
- contextsynapse/a2a/streaming.py +92 -0
- contextsynapse/a2a/task_manager.py +275 -0
- contextsynapse/adapters/__init__.py +98 -0
- contextsynapse/adapters/_base.py +298 -0
- contextsynapse/adapters/autogen/__init__.py +4 -0
- contextsynapse/adapters/autogen/tools.py +34 -0
- contextsynapse/adapters/crewai/__init__.py +4 -0
- contextsynapse/adapters/crewai/tools.py +63 -0
- contextsynapse/adapters/langchain/__init__.py +19 -0
- contextsynapse/adapters/langchain/message_history.py +17 -0
- contextsynapse/adapters/langchain/retriever.py +158 -0
- contextsynapse/adapters/langchain/tools.py +43 -0
- contextsynapse/adapters/langgraph/__init__.py +21 -0
- contextsynapse/adapters/langgraph/checkpoint.py +223 -0
- contextsynapse/adapters/langgraph/context_tools.py +341 -0
- contextsynapse/adapters/langgraph/message_history.py +138 -0
- contextsynapse/adapters/langgraph/tools.py +43 -0
- contextsynapse/adapters/llamaindex/__init__.py +4 -0
- contextsynapse/adapters/llamaindex/tools.py +64 -0
- contextsynapse/adapters/openai/__init__.py +24 -0
- contextsynapse/adapters/openai/tools.py +206 -0
- contextsynapse/adapters/pydantic_ai/__init__.py +4 -0
- contextsynapse/adapters/pydantic_ai/tools.py +36 -0
- contextsynapse/adapters/swarm/__init__.py +4 -0
- contextsynapse/adapters/swarm/tools.py +44 -0
- contextsynapse/agents/__init__.py +6 -0
- contextsynapse/agents/auto_capture.py +80 -0
- contextsynapse/agents/dispatcher.py +299 -0
- contextsynapse/agents/notifications.py +112 -0
- contextsynapse/aiql/__init__.py +71 -0
- contextsynapse/aiql/cache.py +341 -0
- contextsynapse/aiql/compiler/__init__.py +62 -0
- contextsynapse/aiql/compiler/optimizer.py +126 -0
- contextsynapse/aiql/compiler/planner.py +366 -0
- contextsynapse/aiql/compiler/statistics.py +235 -0
- contextsynapse/aiql/compiler/validator.py +425 -0
- contextsynapse/aiql/engine/__init__.py +11 -0
- contextsynapse/aiql/engine/chunk_storage.py +2584 -0
- contextsynapse/aiql/engine/executor.py +7737 -0
- contextsynapse/aiql/engine/extraction_integration.py +442 -0
- contextsynapse/aiql/engine/graph_builder.py +405 -0
- contextsynapse/aiql/engine/node_creation_from_normalized.py +691 -0
- contextsynapse/aiql/engine/performance_monitor.py +289 -0
- contextsynapse/aiql/engine/postprocessing.py +365 -0
- contextsynapse/aiql/engine/ray_stage_executors.py +918 -0
- contextsynapse/aiql/engine/redis_cache.py +106 -0
- contextsynapse/aiql/engine/streaming_json.py +366 -0
- contextsynapse/aiql/engine/streaming_parquet.py +568 -0
- contextsynapse/aiql/engine/streaming_ray_chunking.py +419 -0
- contextsynapse/aiql/grammar/__init__.py +14 -0
- contextsynapse/aiql/grammar/aiql_grammar.py +1822 -0
- contextsynapse/aiql/grammar/base.py +71 -0
- contextsynapse/aiql/parser/__init__.py +46 -0
- contextsynapse/aiql/parser/aiql_parser.py +11330 -0
- contextsynapse/aiql/parser/base_parser.py +47 -0
- contextsynapse/api/__init__.py +5 -0
- contextsynapse/api/a2a_router.py +233 -0
- contextsynapse/api/admin_router.py +140 -0
- contextsynapse/api/agent_worker_router.py +978 -0
- contextsynapse/api/algorithms_router.py +317 -0
- contextsynapse/api/api.py +4144 -0
- contextsynapse/api/audit.py +204 -0
- contextsynapse/api/auth.py +441 -0
- contextsynapse/api/auth_router.py +537 -0
- contextsynapse/api/billing.py +261 -0
- contextsynapse/api/billing_router.py +275 -0
- contextsynapse/api/boundary_router.py +452 -0
- contextsynapse/api/cognition_router.py +116 -0
- contextsynapse/api/connector_router.py +237 -0
- contextsynapse/api/context_router.py +1619 -0
- contextsynapse/api/dashboard_router.py +11367 -0
- contextsynapse/api/errors.py +183 -0
- contextsynapse/api/events.py +88 -0
- contextsynapse/api/experiment_bootstrap.py +321 -0
- contextsynapse/api/experiment_orchestrator.py +1078 -0
- contextsynapse/api/experiment_router.py +2089 -0
- contextsynapse/api/feature_gate.py +89 -0
- contextsynapse/api/federation_router.py +108 -0
- contextsynapse/api/integrations.py +567 -0
- contextsynapse/api/integrations_router.py +461 -0
- contextsynapse/api/intelligence_router.py +1028 -0
- contextsynapse/api/metering.py +155 -0
- contextsynapse/api/metrics.py +112 -0
- contextsynapse/api/models.py +38 -0
- contextsynapse/api/monitoring_router.py +174 -0
- contextsynapse/api/pipeline_router.py +1437 -0
- contextsynapse/api/playground_conn.py +116 -0
- contextsynapse/api/projects_router.py +131 -0
- contextsynapse/api/queries_router.py +282 -0
- contextsynapse/api/quota.py +95 -0
- contextsynapse/api/rate_limit.py +64 -0
- contextsynapse/api/search_router.py +261 -0
- contextsynapse/api/shield_router.py +447 -0
- contextsynapse/api/tenant_guard.py +103 -0
- contextsynapse/api/tenant_quotas.py +231 -0
- contextsynapse/api/tenants.py +305 -0
- contextsynapse/api/users.py +646 -0
- contextsynapse/api/v1.py +167 -0
- contextsynapse/api/vertical_builder_router.py +387 -0
- contextsynapse/benchmark/__init__.py +15 -0
- contextsynapse/benchmark/__main__.py +64 -0
- contextsynapse/benchmark/agents.py +338 -0
- contextsynapse/benchmark/live_ab.py +338 -0
- contextsynapse/benchmark/reporter.py +149 -0
- contextsynapse/benchmark/runner.py +264 -0
- contextsynapse/benchmark/savings.py +266 -0
- contextsynapse/benchmark/token_counter.py +212 -0
- contextsynapse/benchmark/workloads.py +289 -0
- contextsynapse/buffer/__init__.py +154 -0
- contextsynapse/buffer/base.py +257 -0
- contextsynapse/buffer/duckdb_buffer.py +246 -0
- contextsynapse/buffer/file_buffer.py +229 -0
- contextsynapse/buffer/lmdb_buffer.py +286 -0
- contextsynapse/buffer/local_buffer.py +154 -0
- contextsynapse/buffer/redis_buffer.py +211 -0
- contextsynapse/buffer/sqlite_buffer.py +266 -0
- contextsynapse/cache.py +2 -0
- contextsynapse/cli/__init__.py +40 -0
- contextsynapse/cli/cli.py +475 -0
- contextsynapse/cli/config_cli.py +177 -0
- contextsynapse/cli/scaffold.py +465 -0
- contextsynapse/cognition/__init__.py +31 -0
- contextsynapse/cognition/derivation.py +55 -0
- contextsynapse/cognition/events.py +135 -0
- contextsynapse/cognition/feedback.py +52 -0
- contextsynapse/cognition/hallucination.py +90 -0
- contextsynapse/cognition/invalidation.py +70 -0
- contextsynapse/cognition/read_tracker.py +50 -0
- contextsynapse/collaboration.py +2 -0
- contextsynapse/comparison.py +2 -0
- contextsynapse/config/__init__.py +10 -0
- contextsynapse/config/connectors/amfi_nav.yaml +18 -0
- contextsynapse/config/connectors/auto_sector.yaml +20 -0
- contextsynapse/config/connectors/banking_sector.yaml +20 -0
- contextsynapse/config/connectors/energy_sector.yaml +20 -0
- contextsynapse/config/connectors/fmcg_sector.yaml +20 -0
- contextsynapse/config/connectors/nsdl_fpi.yaml +9 -0
- contextsynapse/config/connectors/nse_price.yaml +61 -0
- contextsynapse/config/connectors/pharma_sector.yaml +20 -0
- contextsynapse/config/connectors/rbi_dbie.yaml +12 -0
- contextsynapse/config/context_presets/ai_research.json +25 -0
- contextsynapse/config/context_presets/chatgpt_conversations.json +19 -0
- contextsynapse/config/context_presets/claude_conversations.json +19 -0
- contextsynapse/config/context_presets/legal_compliance.json +21 -0
- contextsynapse/config/context_presets/meeting_notes.json +21 -0
- contextsynapse/config/context_presets/slack_engineering.json +21 -0
- contextsynapse/config/context_presets/tech_climate.json +24 -0
- contextsynapse/config/context_presets/toi_politics.json +25 -0
- contextsynapse/config/database_config.py +453 -0
- contextsynapse/config/deployment.py +221 -0
- contextsynapse/config/gpt_action_schema.json +164 -0
- contextsynapse/config/indicators/india_macro.yaml +213 -0
- contextsynapse/config/logging_config.py +88 -0
- contextsynapse/config/mode_config.py +223 -0
- contextsynapse/config/schemas/api_spec.yaml +48 -0
- contextsynapse/config/schemas/architecture_doc.yaml +51 -0
- contextsynapse/config/schemas/chat_history.yaml +90 -0
- contextsynapse/config/schemas/chatgpt_conversation.yaml +101 -0
- contextsynapse/config/schemas/claude_conversation.yaml +148 -0
- contextsynapse/config/schemas/contract.yaml +48 -0
- contextsynapse/config/schemas/conversation.yaml +167 -0
- contextsynapse/config/schemas/database.yaml +74 -0
- contextsynapse/config/schemas/decision.yaml +72 -0
- contextsynapse/config/schemas/ecommerce.yaml +56 -0
- contextsynapse/config/schemas/education.yaml +42 -0
- contextsynapse/config/schemas/healthcare.yaml +133 -0
- contextsynapse/config/schemas/hr_document.yaml +48 -0
- contextsynapse/config/schemas/invoice.yaml +40 -0
- contextsynapse/config/schemas/knowledge_base.yaml +75 -0
- contextsynapse/config/schemas/legal.yaml +42 -0
- contextsynapse/config/schemas/marketing_content.yaml +48 -0
- contextsynapse/config/schemas/meeting_notes.yaml +51 -0
- contextsynapse/config/schemas/news_article.yaml +61 -0
- contextsynapse/config/schemas/real_estate.yaml +49 -0
- contextsynapse/config/schemas/requirements_doc.yaml +48 -0
- contextsynapse/config/schemas/research_paper.yaml +56 -0
- contextsynapse/config/schemas/resume.yaml +49 -0
- contextsynapse/config/schemas/retail.yaml +42 -0
- contextsynapse/config/schemas/rule_meta.yaml +173 -0
- contextsynapse/config/schemas/rules.yaml +72 -0
- contextsynapse/config/schemas/screener_meta.yaml +236 -0
- contextsynapse/config/schemas/sdlc.yaml +103 -0
- contextsynapse/config/schemas/session_graph.yaml +172 -0
- contextsynapse/config/schemas/support_ticket.yaml +48 -0
- contextsynapse/config/schemas/web.yaml +64 -0
- contextsynapse/config/sensors/earnings_calendar.yaml +52 -0
- contextsynapse/config/sensors/global_risk.yaml +53 -0
- contextsynapse/config/sensors/government_policy.yaml +54 -0
- contextsynapse/config/sensors/supply_chain.yaml +50 -0
- contextsynapse/config/sensors/templates/behavioral.yaml +56 -0
- contextsynapse/config/sensors/templates/equity_sentiment.yaml +48 -0
- contextsynapse/config/sensors/templates/global_macro.yaml +47 -0
- contextsynapse/config/sensors/templates/market_data.yaml +118 -0
- contextsynapse/config/sensors/templates/sector_technical.yaml +47 -0
- contextsynapse/config/sensors/weather.yaml +52 -0
- contextsynapse/config/storage_strategy.py +202 -0
- contextsynapse/config/templates/competitive_intel.yaml +39 -0
- contextsynapse/config/templates/geopolitical_risk.yaml +46 -0
- contextsynapse/config/templates/market_analysis.yaml +58 -0
- contextsynapse/connectors/__init__.py +15 -0
- contextsynapse/connectors/api_router.py +121 -0
- contextsynapse/connectors/base.py +357 -0
- contextsynapse/connectors/financial/audio.py +170 -0
- contextsynapse/connectors/financial/youtube.py +272 -0
- contextsynapse/connectors/github.py +164 -0
- contextsynapse/connectors/jira.py +120 -0
- contextsynapse/connectors/kafka_connector.py +124 -0
- contextsynapse/connectors/pipeline_connector.py +747 -0
- contextsynapse/connectors/registry.py +116 -0
- contextsynapse/connectors/scheduler.py +87 -0
- contextsynapse/connectors/universal.py +360 -0
- contextsynapse/context/__init__.py +96 -0
- contextsynapse/context/__main__.py +4 -0
- contextsynapse/context/acl.py +125 -0
- contextsynapse/context/agent_card.py +201 -0
- contextsynapse/context/agent_memory.py +814 -0
- contextsynapse/context/agents.py +472 -0
- contextsynapse/context/agents_redis.py +391 -0
- contextsynapse/context/assembled.py +204 -0
- contextsynapse/context/attribution.py +113 -0
- contextsynapse/context/blob.py +184 -0
- contextsynapse/context/boundaries.py +187 -0
- contextsynapse/context/boundary.py +507 -0
- contextsynapse/context/bundle.py +155 -0
- contextsynapse/context/cli.py +519 -0
- contextsynapse/context/collaboration.py +165 -0
- contextsynapse/context/compiler.py +604 -0
- contextsynapse/context/composite.py +536 -0
- contextsynapse/context/compression.py +147 -0
- contextsynapse/context/context_manager.py +888 -0
- contextsynapse/context/context_schema.py +90 -0
- contextsynapse/context/context_schema.yaml +105 -0
- contextsynapse/context/context_units.py +891 -0
- contextsynapse/context/conversation.py +488 -0
- contextsynapse/context/dedup.py +207 -0
- contextsynapse/context/document_processor.py +698 -0
- contextsynapse/context/embedding_hooks.py +338 -0
- contextsynapse/context/execution_schema.py +274 -0
- contextsynapse/context/fan_out.py +138 -0
- contextsynapse/context/frozen.py +80 -0
- contextsynapse/context/gravity.py +227 -0
- contextsynapse/context/hub.py +1401 -0
- contextsynapse/context/ingest.py +391 -0
- contextsynapse/context/injection.py +226 -0
- contextsynapse/context/interaction_graphifier.py +562 -0
- contextsynapse/context/layers.py +574 -0
- contextsynapse/context/projection.py +1195 -0
- contextsynapse/context/promotion.py +634 -0
- contextsynapse/context/proof.py +131 -0
- contextsynapse/context/propagation.py +577 -0
- contextsynapse/context/pubsub.py +135 -0
- contextsynapse/context/quality.py +1054 -0
- contextsynapse/context/quality_tracker.py +270 -0
- contextsynapse/context/scoping.py +370 -0
- contextsynapse/context/seed.py +992 -0
- contextsynapse/context/session.py +1142 -0
- contextsynapse/context/session_graph.py +593 -0
- contextsynapse/context/session_memory.py +309 -0
- contextsynapse/context/session_resolver.py +111 -0
- contextsynapse/context/skill_learning.py +237 -0
- contextsynapse/context/smart_budget.py +129 -0
- contextsynapse/context/source_policy.py +242 -0
- contextsynapse/context/store_factory.py +53 -0
- contextsynapse/context/sync.py +648 -0
- contextsynapse/context/token.py +236 -0
- contextsynapse/context/vector_integration.py +297 -0
- contextsynapse/context/webhooks.py +194 -0
- contextsynapse/context/working_memory.py +224 -0
- contextsynapse/core/__init__.py +18 -0
- contextsynapse/core/archiver.py +237 -0
- contextsynapse/core/change_stream.py +282 -0
- contextsynapse/core/checkpoint.py +310 -0
- contextsynapse/core/cloud_storage.py +387 -0
- contextsynapse/core/context_state.py +651 -0
- contextsynapse/core/cron.py +324 -0
- contextsynapse/core/datasource.py +643 -0
- contextsynapse/core/db.py +289 -0
- contextsynapse/core/federation.py +283 -0
- contextsynapse/core/graph_coordinator.py +201 -0
- contextsynapse/core/graph_intelligence.py +388 -0
- contextsynapse/core/graph_structures.py +106 -0
- contextsynapse/core/graph_sync.py +157 -0
- contextsynapse/core/hybrid_graph_storage.py +2998 -0
- contextsynapse/core/lifecycle.py +691 -0
- contextsynapse/core/multiworker.py +378 -0
- contextsynapse/core/pruning.py +312 -0
- contextsynapse/core/redis_registry.py +524 -0
- contextsynapse/core/registry.py +1043 -0
- contextsynapse/core/registry_factory.py +51 -0
- contextsynapse/core/registry_metadata.py +294 -0
- contextsynapse/core/replay.py +354 -0
- contextsynapse/core/replication.py +339 -0
- contextsynapse/core/time_travel.py +260 -0
- contextsynapse/core/write_behind.py +152 -0
- contextsynapse/core/write_context.py +39 -0
- contextsynapse/db/__init__.py +1 -0
- contextsynapse/db/postgres.py +267 -0
- contextsynapse/db/profile.py +236 -0
- contextsynapse/db/rules.py +328 -0
- contextsynapse/demo/__init__.py +0 -0
- contextsynapse/demo/report.py +147 -0
- contextsynapse/demo/runner.py +520 -0
- contextsynapse/demo/scenario.py +165 -0
- contextsynapse/demo/session_demo.py +280 -0
- contextsynapse/demo/session_report.py +143 -0
- contextsynapse/demo/universal_runner.py +257 -0
- contextsynapse/engine/__init__.py +15 -0
- contextsynapse/engine/core.py +555 -0
- contextsynapse/extraction/__init__.py +69 -0
- contextsynapse/extraction/cli.py +274 -0
- contextsynapse/extraction/config.py +107 -0
- contextsynapse/extraction/examples/example_usage.py +118 -0
- contextsynapse/extraction/examples/sample_manifest.json +53 -0
- contextsynapse/extraction/examples/sample_normalized.json +185 -0
- contextsynapse/extraction/extract_engine.py +440 -0
- contextsynapse/extraction/extractors/__init__.py +37 -0
- contextsynapse/extraction/extractors/chat_export_extractor.py +189 -0
- contextsynapse/extraction/extractors/csv_extractor.py +83 -0
- contextsynapse/extraction/extractors/docx_extractor.py +129 -0
- contextsynapse/extraction/extractors/excel_extractor.py +152 -0
- contextsynapse/extraction/extractors/html_extractor.py +146 -0
- contextsynapse/extraction/extractors/pdf_extractor.py +635 -0
- contextsynapse/extraction/extractors/pdf_extractor_layoutparser.py +408 -0
- contextsynapse/extraction/extractors/register_extractors.py +63 -0
- contextsynapse/extraction/extractors/text_extractor.py +65 -0
- contextsynapse/extraction/extractors/txt_extractor.py +120 -0
- contextsynapse/extraction/extractors/website_extractor.py +246 -0
- contextsynapse/extraction/fact_extractor.py +236 -0
- contextsynapse/extraction/file_manager.py +353 -0
- contextsynapse/extraction/hierarchy.py +239 -0
- contextsynapse/extraction/id_generator.py +450 -0
- contextsynapse/extraction/layout_detector.py +409 -0
- contextsynapse/extraction/llm_entity_extractor.py +301 -0
- contextsynapse/extraction/normalized_store.py +480 -0
- contextsynapse/extraction/normalizer.py +594 -0
- contextsynapse/extraction/parquet_writer.py +598 -0
- contextsynapse/extraction/post_processors/__init__.py +40 -0
- contextsynapse/extraction/post_processors/column_reorganizer.py +507 -0
- contextsynapse/extraction/ray_normalization.py +233 -0
- contextsynapse/extraction/ray_runner.py +207 -0
- contextsynapse/extraction/redis_schema_registry.py +222 -0
- contextsynapse/extraction/registry.py +204 -0
- contextsynapse/extraction/schema_loader.py +663 -0
- contextsynapse/extraction/schema_registry.py +230 -0
- contextsynapse/extraction/semantic_normalizer.py +245 -0
- contextsynapse/extraction/version_manager.py +314 -0
- contextsynapse/gateway/__init__.py +24 -0
- contextsynapse/gateway/action_emitter.py +212 -0
- contextsynapse/gateway/cost_tracker.py +508 -0
- contextsynapse/gateway/gateway.py +377 -0
- contextsynapse/gateway/policy.py +303 -0
- contextsynapse/governance/__init__.py +13 -0
- contextsynapse/governance/layer.py +513 -0
- contextsynapse/ingestion/__init__.py +15 -0
- contextsynapse/ingestion/amplifier.py +288 -0
- contextsynapse/ingestion/async_ingest.py +463 -0
- contextsynapse/ingestion/chunker.py +303 -0
- contextsynapse/ingestion/chunking.py +58 -0
- contextsynapse/ingestion/cleaner.py +190 -0
- contextsynapse/ingestion/cleanse.py +252 -0
- contextsynapse/ingestion/connectors/__init__.py +38 -0
- contextsynapse/ingestion/connectors/base.py +300 -0
- contextsynapse/ingestion/connectors/chatgpt_memory.py +247 -0
- contextsynapse/ingestion/connectors/claude_memory.py +274 -0
- contextsynapse/ingestion/connectors/sap_ingestor.py +208 -0
- contextsynapse/ingestion/content_detector.py +80 -0
- contextsynapse/ingestion/content_monitor.py +502 -0
- contextsynapse/ingestion/dedup.py +106 -0
- contextsynapse/ingestion/feed.py +640 -0
- contextsynapse/ingestion/filters.py +461 -0
- contextsynapse/ingestion/graph_builder.py +705 -0
- contextsynapse/ingestion/input_classifier.py +307 -0
- contextsynapse/ingestion/job_manager.py +571 -0
- contextsynapse/ingestion/llm_extractor.py +610 -0
- contextsynapse/ingestion/orchestrator.py +116 -0
- contextsynapse/ingestion/parsers/__init__.py +19 -0
- contextsynapse/ingestion/parsers/graph_parser_registry.py +103 -0
- contextsynapse/ingestion/parsers/graphml_parser.py +141 -0
- contextsynapse/ingestion/parsers/jsonld_parser.py +171 -0
- contextsynapse/ingestion/parsers/rdf_parser.py +150 -0
- contextsynapse/ingestion/pipeline_context.py +228 -0
- contextsynapse/ingestion/pipeline_store.py +1195 -0
- contextsynapse/ingestion/queue.py +133 -0
- contextsynapse/ingestion/reprocess.py +179 -0
- contextsynapse/ingestion/scenario_router.py +224 -0
- contextsynapse/ingestion/schema_extractor.py +759 -0
- contextsynapse/ingestion/schema_validator.py +274 -0
- contextsynapse/ingestion/sdlc_ingest.py +87 -0
- contextsynapse/ingestion/smart_ingest.py +2451 -0
- contextsynapse/ingestion/source_connector.py +171 -0
- contextsynapse/ingestion/stage_executor.py +2095 -0
- contextsynapse/ingestion/stages/__init__.py +9 -0
- contextsynapse/ingestion/stages/tabular_to_graph.py +289 -0
- contextsynapse/ingestion/strategies.py +386 -0
- contextsynapse/ingestion/universal/__init__.py +4 -0
- contextsynapse/ingestion/universal/_operator_registry.py +59 -0
- contextsynapse/ingestion/universal/ingest_content.py +32 -0
- contextsynapse/ingestion/universal/operators/__init__.py +1 -0
- contextsynapse/ingestion/universal/operators/base.py +19 -0
- contextsynapse/ingestion/universal/operators/build_edges.py +75 -0
- contextsynapse/ingestion/universal/operators/cluster_topics.py +397 -0
- contextsynapse/ingestion/universal/operators/deduplicate.py +45 -0
- contextsynapse/ingestion/universal/operators/detect_signals.py +90 -0
- contextsynapse/ingestion/universal/operators/embed.py +80 -0
- contextsynapse/ingestion/universal/operators/extract_entities.py +253 -0
- contextsynapse/ingestion/universal/operators/extract_preferences.py +117 -0
- contextsynapse/ingestion/universal/operators/filter_content.py +69 -0
- contextsynapse/ingestion/universal/operators/index_bm25.py +52 -0
- contextsynapse/ingestion/universal/operators/infer_domains.py +69 -0
- contextsynapse/ingestion/universal/operators/link_cross_reference.py +210 -0
- contextsynapse/ingestion/universal/operators/parse_records.py +66 -0
- contextsynapse/ingestion/universal/operators/resolve_entities.py +261 -0
- contextsynapse/ingestion/universal/operators/scanners/__init__.py +16 -0
- contextsynapse/ingestion/universal/operators/scanners/edges.py +173 -0
- contextsynapse/ingestion/universal/operators/scanners/git.py +187 -0
- contextsynapse/ingestion/universal/operators/scanners/github.py +135 -0
- contextsynapse/ingestion/universal/operators/scanners/github_api.py +509 -0
- contextsynapse/ingestion/universal/operators/scanners/helpers.py +67 -0
- contextsynapse/ingestion/universal/operators/scanners/jira.py +65 -0
- contextsynapse/ingestion/universal/operators/scanners/llm_enrichment.py +82 -0
- contextsynapse/ingestion/universal/operators/scanners/repo.py +149 -0
- contextsynapse/ingestion/universal/operators/sdlc_scan.py +213 -0
- contextsynapse/ingestion/universal/operators/spec_scanner.py +149 -0
- contextsynapse/ingestion/universal/operators/store_documents.py +72 -0
- contextsynapse/ingestion/universal/operators/synthesize_cu.py +180 -0
- contextsynapse/ingestion/universal/operators/validate_gate.py +65 -0
- contextsynapse/ingestion/universal/parsers/__init__.py +5 -0
- contextsynapse/ingestion/universal/parsers/record_parser.py +203 -0
- contextsynapse/ingestion/universal/parsers/turn_parser.py +329 -0
- contextsynapse/ingestion/universal/shared_signals.py +161 -0
- contextsynapse/ingestion/universal/stage_executor.py +219 -0
- contextsynapse/ingestion/web_crawler.py +265 -0
- contextsynapse/intelligence/__init__.py +53 -0
- contextsynapse/intelligence/alerts.py +198 -0
- contextsynapse/intelligence/collector.py +655 -0
- contextsynapse/intelligence/comparison.py +198 -0
- contextsynapse/intelligence/config.py +56 -0
- contextsynapse/intelligence/conflict_detector.py +182 -0
- contextsynapse/intelligence/context_gaps.py +192 -0
- contextsynapse/intelligence/context_radar.py +135 -0
- contextsynapse/intelligence/correlation_engine.py +416 -0
- contextsynapse/intelligence/correlation_template.py +120 -0
- contextsynapse/intelligence/dedup.py +296 -0
- contextsynapse/intelligence/event_bus.py +91 -0
- contextsynapse/intelligence/feedback_loop.py +101 -0
- contextsynapse/intelligence/freshness.py +307 -0
- contextsynapse/intelligence/fundamental_feed.py +551 -0
- contextsynapse/intelligence/geo_data.py +170 -0
- contextsynapse/intelligence/geo_reference.py +112 -0
- contextsynapse/intelligence/graph_fusion.py +465 -0
- contextsynapse/intelligence/heuristics.py +176 -0
- contextsynapse/intelligence/impact_tracker.py +336 -0
- contextsynapse/intelligence/macro_indicators.py +319 -0
- contextsynapse/intelligence/ocr.py +104 -0
- contextsynapse/intelligence/persistence.py +267 -0
- contextsynapse/intelligence/pipeline_health.py +130 -0
- contextsynapse/intelligence/price_feed.py +221 -0
- contextsynapse/intelligence/rate_limiter.py +130 -0
- contextsynapse/intelligence/reactive.py +411 -0
- contextsynapse/intelligence/runtime_context.py +390 -0
- contextsynapse/intelligence/sentiment_decay.py +426 -0
- contextsynapse/intelligence/session.py +277 -0
- contextsynapse/intelligence/signal_hierarchy.py +438 -0
- contextsynapse/intelligence/signals.py +185 -0
- contextsynapse/intelligence/source_watcher.py +132 -0
- contextsynapse/intelligence/table_enricher.py +256 -0
- contextsynapse/intelligence/tagger.py +319 -0
- contextsynapse/intelligence/timeseries.py +209 -0
- contextsynapse/intelligence/tracker.py +318 -0
- contextsynapse/intelligence/watchdog.py +392 -0
- contextsynapse/intelligence/watchdog_manager.py +263 -0
- contextsynapse/intelligence/webhook_receiver.py +165 -0
- contextsynapse/intelligence/weight_learner.py +234 -0
- contextsynapse/llm/__init__.py +8 -0
- contextsynapse/llm/client.py +348 -0
- contextsynapse/llm/rate_limiter.py +166 -0
- contextsynapse/logging_config.py +2 -0
- contextsynapse/marketplace/__init__.py +7 -0
- contextsynapse/marketplace/registry.py +173 -0
- contextsynapse/mcp/__init__.py +11 -0
- contextsynapse/mcp/__main__.py +4 -0
- contextsynapse/mcp/auth_middleware.py +212 -0
- contextsynapse/mcp/connection_pool.py +128 -0
- contextsynapse/mcp/server.py +986 -0
- contextsynapse/mcp/session_context.py +67 -0
- contextsynapse/memory/__init__.py +34 -0
- contextsynapse/memory/engine.py +475 -0
- contextsynapse/memory/temporal.py +327 -0
- contextsynapse/metadata/__init__.py +12 -0
- contextsynapse/metadata/metadata_db.py +272 -0
- contextsynapse/metadata/metadata_query_tool.py +300 -0
- contextsynapse/metadata/metadata_tracker.py +425 -0
- contextsynapse/models/__init__.py +27 -0
- contextsynapse/models/embedding_service.py +360 -0
- contextsynapse/models/model_registry.py +228 -0
- contextsynapse/multiworker.py +2 -0
- contextsynapse/pipelines/__init__.py +1 -0
- contextsynapse/pipelines/executor.py +851 -0
- contextsynapse/pipelines/filters.py +189 -0
- contextsynapse/pipelines/models.py +176 -0
- contextsynapse/pipelines/scheduler.py +268 -0
- contextsynapse/playground/__init__.py +1 -0
- contextsynapse/playground/templates.py +85 -0
- contextsynapse/plugins/__init__.py +43 -0
- contextsynapse/plugins/api.py +66 -0
- contextsynapse/plugins/base.py +350 -0
- contextsynapse/plugins/domain_interface.py +508 -0
- contextsynapse/plugins/domain_loader.py +241 -0
- contextsynapse/plugins/loader.py +148 -0
- contextsynapse/plugins/registry.py +265 -0
- contextsynapse/project/__init__.py +11 -0
- contextsynapse/project/code_context.py +807 -0
- contextsynapse/project/connectors/__init__.py +4 -0
- contextsynapse/project/connectors/github_connector.py +113 -0
- contextsynapse/project/connectors/jira_connector.py +160 -0
- contextsynapse/project/graph.py +1023 -0
- contextsynapse/project/project_context.py +545 -0
- contextsynapse/project/scanner_registry.py +61 -0
- contextsynapse/project/schema_manager.py +322 -0
- contextsynapse/project/schemas/knowledge.yaml +59 -0
- contextsynapse/project/schemas/sdlc.yaml +369 -0
- contextsynapse/project/sdlc_schema.py +172 -0
- contextsynapse/project/spec_parser.py +85 -0
- contextsynapse/project/task_lock.py +181 -0
- contextsynapse/project/task_stream.py +203 -0
- contextsynapse/project/team_tools.py +537 -0
- contextsynapse/py.typed +0 -0
- contextsynapse/realtime/__init__.py +6 -0
- contextsynapse/realtime/collaboration.py +147 -0
- contextsynapse/rules/__init__.py +10 -0
- contextsynapse/rules/engine.py +116 -0
- contextsynapse/rules/evaluators/__init__.py +6 -0
- contextsynapse/rules/evaluators/aggregate.py +205 -0
- contextsynapse/rules/evaluators/custom.py +170 -0
- contextsynapse/rules/evaluators/pre_action.py +125 -0
- contextsynapse/rules/evaluators/temporal.py +129 -0
- contextsynapse/rules/loader.py +52 -0
- contextsynapse/rules/models.py +124 -0
- contextsynapse/rules/universal.py +393 -0
- contextsynapse/scheduler.py +229 -0
- contextsynapse/schema/__init__.py +42 -0
- contextsynapse/schema/compiler.py +252 -0
- contextsynapse/schema/composer.py +158 -0
- contextsynapse/schema/dedup.py +73 -0
- contextsynapse/schema/derivation.py +172 -0
- contextsynapse/schema/sdl.py +326 -0
- contextsynapse/schema/validation_gate.py +124 -0
- contextsynapse/sdk/__init__.py +63 -0
- contextsynapse/sdk/agent.py +214 -0
- contextsynapse/sdk/client.py +269 -0
- contextsynapse/sdk/exceptions.py +23 -0
- contextsynapse/sdk/models.py +78 -0
- contextsynapse/sdk/session.py +408 -0
- contextsynapse/sdk/tracked.py +218 -0
- contextsynapse/sdk/worker.py +266 -0
- contextsynapse/sdk/workspace_client.py +98 -0
- contextsynapse/sdk/ws.py +41 -0
- contextsynapse/search/__init__.py +20 -0
- contextsynapse/search/embedding_cache.py +140 -0
- contextsynapse/search/enhanced_search.py +152 -0
- contextsynapse/search/fulltext.py +130 -0
- contextsynapse/search/graph_search.py +634 -0
- contextsynapse/search/lmdb_index.py +1218 -0
- contextsynapse/search/nl_to_aiql.py +199 -0
- contextsynapse/search/rag.py +1346 -0
- contextsynapse/search/rag_cache.py +167 -0
- contextsynapse/search/reasoning_chain.py +231 -0
- contextsynapse/search/redis_search.py +207 -0
- contextsynapse/search/retrieval_quality.py +314 -0
- contextsynapse/search/semantic_query.py +455 -0
- contextsynapse/search/text_resolver.py +159 -0
- contextsynapse/search/whoosh_search.py +373 -0
- contextsynapse/security/__init__.py +17 -0
- contextsynapse/security/audit.py +297 -0
- contextsynapse/security/audit_logger.py +97 -0
- contextsynapse/security/audit_trail.py +270 -0
- contextsynapse/security/auth_unified.py +284 -0
- contextsynapse/security/auto_tagger.py +230 -0
- contextsynapse/security/data_security.py +218 -0
- contextsynapse/security/encryption.py +207 -0
- contextsynapse/security/identity.py +447 -0
- contextsynapse/security/jwt_identity.py +59 -0
- contextsynapse/security/middleware.py +336 -0
- contextsynapse/security/pii.py +233 -0
- contextsynapse/security/rbac.py +96 -0
- contextsynapse/security/rls.py +205 -0
- contextsynapse/security/sanitize.py +233 -0
- contextsynapse/security/scoped_encryption.py +131 -0
- contextsynapse/security/tenant.py +401 -0
- contextsynapse/shield/__init__.py +21 -0
- contextsynapse/shield/anomaly.py +56 -0
- contextsynapse/shield/permissions.py +99 -0
- contextsynapse/shield/profile.py +103 -0
- contextsynapse/shield/shield.py +108 -0
- contextsynapse/shield/trust_engine.py +69 -0
- contextsynapse/skills/__init__.py +14 -0
- contextsynapse/skills/engine.py +233 -0
- contextsynapse/skills/loader.py +59 -0
- contextsynapse/skills/models.py +139 -0
- contextsynapse/storage/__init__.py +7 -0
- contextsynapse/storage/cache.py +208 -0
- contextsynapse/storage/columnar_store_v2.py +178 -0
- contextsynapse/storage/csr_graph_storage.py +587 -0
- contextsynapse/storage/csr_store.py +388 -0
- contextsynapse/storage/document_store.py +491 -0
- contextsynapse/storage/hnsw_index.py +294 -0
- contextsynapse/storage/hybrid_store_v2.py +278 -0
- contextsynapse/storage/lmdb_graph_storage.py +366 -0
- contextsynapse/storage/migration.py +279 -0
- contextsynapse/storage/namespace_store.py +346 -0
- contextsynapse/storage/pure_graph_storage.py +185 -0
- contextsynapse/storage/redis_graph_adapter.py +186 -0
- contextsynapse/storage/redis_graph_storage.py +375 -0
- contextsynapse/storage/router/__init__.py +29 -0
- contextsynapse/storage/router/duckdb_store.py +398 -0
- contextsynapse/storage/router/factory.py +83 -0
- contextsynapse/storage/router/interface.py +125 -0
- contextsynapse/storage/router/postgres_store.py +339 -0
- contextsynapse/storage/router/resolver.py +192 -0
- contextsynapse/storage/router/router.py +300 -0
- contextsynapse/storage/single_file_storage.py +391 -0
- contextsynapse/storage/storage_manager.py +214 -0
- contextsynapse/storage/storage_query_optimizer.py +314 -0
- contextsynapse/storage/wal.py +359 -0
- contextsynapse/temporal/__init__.py +0 -0
- contextsynapse/temporal/storage.py +106 -0
- contextsynapse/tests/__init__.py +11 -0
- contextsynapse/tests/regression/__init__.py +1 -0
- contextsynapse/tests/regression/add_metadata.py +395 -0
- contextsynapse/tests/regression/add_skip_flags.py +85 -0
- contextsynapse/tests/regression/cases/test_basic_create_node.yaml +20 -0
- contextsynapse/tests/regression/cases/test_basic_select.yaml +21 -0
- contextsynapse/tests/regression/cases/test_blockchain_audit_trail.yaml +37 -0
- contextsynapse/tests/regression/cases/test_blockchain_audit_trail_filtered.yaml +39 -0
- contextsynapse/tests/regression/cases/test_blockchain_blocks_range.yaml +39 -0
- contextsynapse/tests/regression/cases/test_blockchain_get_block.yaml +35 -0
- contextsynapse/tests/regression/cases/test_blockchain_latest_block.yaml +35 -0
- contextsynapse/tests/regression/cases/test_blockchain_length.yaml +37 -0
- contextsynapse/tests/regression/cases/test_blockchain_merkle_root.yaml +37 -0
- contextsynapse/tests/regression/cases/test_blockchain_verify.yaml +35 -0
- contextsynapse/tests/regression/cases/test_blockchain_verify_block.yaml +35 -0
- contextsynapse/tests/regression/cases/test_create_edge.yaml +28 -0
- contextsynapse/tests/regression/cases/test_delete_edge_basic.yaml +29 -0
- contextsynapse/tests/regression/cases/test_delete_node_basic.yaml +29 -0
- contextsynapse/tests/regression/cases/test_evaluation_mrr.yaml +40 -0
- contextsynapse/tests/regression/cases/test_evaluation_ndcg.yaml +40 -0
- contextsynapse/tests/regression/cases/test_evaluation_precision.yaml +40 -0
- contextsynapse/tests/regression/cases/test_evaluation_recall.yaml +40 -0
- contextsynapse/tests/regression/cases/test_group_by_basic.yaml +56 -0
- contextsynapse/tests/regression/cases/test_match_node_basic.yaml +29 -0
- contextsynapse/tests/regression/cases/test_match_node_with_order_limit.yaml +31 -0
- contextsynapse/tests/regression/cases/test_namespace_switch.yaml +18 -0
- contextsynapse/tests/regression/cases/test_pipeline_cascaded.yaml +61 -0
- contextsynapse/tests/regression/cases/test_pipeline_fixed_size_chunking.yaml +48 -0
- contextsynapse/tests/regression/cases/test_pipeline_gpt4_chunking.yaml +54 -0
- contextsynapse/tests/regression/cases/test_pipeline_hybrid_indexing.yaml +57 -0
- contextsynapse/tests/regression/cases/test_pipeline_large_embedding.yaml +52 -0
- contextsynapse/tests/regression/cases/test_pipeline_paragraph_chunking.yaml +49 -0
- contextsynapse/tests/regression/cases/test_pipeline_recursive_chunking.yaml +47 -0
- contextsynapse/tests/regression/cases/test_pipeline_run_pipeline.yaml +56 -0
- contextsynapse/tests/regression/cases/test_pipeline_section_based_chunking.yaml +53 -0
- contextsynapse/tests/regression/cases/test_pipeline_semantic_chunking.yaml +51 -0
- contextsynapse/tests/regression/cases/test_pipeline_with_entity_extraction.yaml +57 -0
- contextsynapse/tests/regression/cases/test_pipeline_with_relationships.yaml +62 -0
- contextsynapse/tests/regression/cases/test_rag_evaluation.yaml +38 -0
- contextsynapse/tests/regression/cases/test_rag_graph_bfs_with_eval.yaml +48 -0
- contextsynapse/tests/regression/cases/test_rag_graph_centrality.yaml +40 -0
- contextsynapse/tests/regression/cases/test_rag_graph_centrality_eval.yaml +35 -0
- contextsynapse/tests/regression/cases/test_rag_graph_community.yaml +40 -0
- contextsynapse/tests/regression/cases/test_rag_graph_community_eval.yaml +35 -0
- contextsynapse/tests/regression/cases/test_rag_graph_dfs_with_eval.yaml +35 -0
- contextsynapse/tests/regression/cases/test_rag_graph_multi_hop_eval.yaml +35 -0
- contextsynapse/tests/regression/cases/test_rag_graph_path.yaml +40 -0
- contextsynapse/tests/regression/cases/test_rag_graph_search_basic.yaml +38 -0
- contextsynapse/tests/regression/cases/test_rag_graph_search_bfs.yaml +52 -0
- contextsynapse/tests/regression/cases/test_rag_graph_search_dfs.yaml +41 -0
- contextsynapse/tests/regression/cases/test_rag_graph_search_multi_hop.yaml +43 -0
- contextsynapse/tests/regression/cases/test_rag_graph_search_shortest_path.yaml +41 -0
- contextsynapse/tests/regression/cases/test_rag_graph_search_weighted.yaml +43 -0
- contextsynapse/tests/regression/cases/test_rag_graph_shortest_path_eval.yaml +35 -0
- contextsynapse/tests/regression/cases/test_rag_graph_traversal.yaml +30 -0
- contextsynapse/tests/regression/cases/test_rag_graph_weighted_eval.yaml +35 -0
- contextsynapse/tests/regression/cases/test_rag_hybrid_search.yaml +33 -0
- contextsynapse/tests/regression/cases/test_rag_hybrid_with_prompt_embedding.yaml +44 -0
- contextsynapse/tests/regression/cases/test_rag_keyword_search.yaml +32 -0
- contextsynapse/tests/regression/cases/test_rag_multi_hop_graph.yaml +32 -0
- contextsynapse/tests/regression/cases/test_rag_path_based.yaml +34 -0
- contextsynapse/tests/regression/cases/test_rag_profile_based.yaml +32 -0
- contextsynapse/tests/regression/cases/test_rag_vector_search.yaml +32 -0
- contextsynapse/tests/regression/cases/test_rag_weighted_graph.yaml +34 -0
- contextsynapse/tests/regression/cases/test_rag_weighted_hybrid.yaml +31 -0
- contextsynapse/tests/regression/cases/test_semantic_boundary_chunking.yaml +57 -0
- contextsynapse/tests/regression/cases/test_semantic_boundary_detection.yaml +33 -0
- contextsynapse/tests/regression/cases/test_semantic_hash_function.yaml +30 -0
- contextsynapse/tests/regression/cases/test_semantic_hash_with_model.yaml +31 -0
- contextsynapse/tests/regression/cases/test_tcs_ingestion_fixed_size.yaml +44 -0
- contextsynapse/tests/regression/cases/test_tcs_ingestion_recursive.yaml +46 -0
- contextsynapse/tests/regression/cases/test_tcs_ingestion_section.yaml +46 -0
- contextsynapse/tests/regression/cases/test_tcs_ingestion_semantic.yaml +44 -0
- contextsynapse/tests/regression/cases/test_time_travel_as_of.yaml +35 -0
- contextsynapse/tests/regression/cases/test_time_travel_at_commit.yaml +33 -0
- contextsynapse/tests/regression/cases/test_time_travel_at_timestamp.yaml +33 -0
- contextsynapse/tests/regression/cases/test_time_travel_for_system_time_all.yaml +37 -0
- contextsynapse/tests/regression/cases/test_time_travel_versions_between.yaml +39 -0
- contextsynapse/tests/regression/cases/test_traverse_basic.yaml +31 -0
- contextsynapse/tests/regression/cases/test_traverse_max_depth.yaml +34 -0
- contextsynapse/tests/regression/cases/test_update_edge_basic.yaml +29 -0
- contextsynapse/tests/regression/evaluation_metrics.py +227 -0
- contextsynapse/tests/regression/regression_runner.py +1081 -0
- contextsynapse/tests/regression/setup_regression_data.py +212 -0
- contextsynapse/tests/regression/test_basic_only.py +84 -0
- contextsynapse/tests/regression/test_namespace_creation.py +29 -0
- contextsynapse/tests/regression/test_single_fix.py +61 -0
- contextsynapse/tests/regression/test_single_query.py +20 -0
- contextsynapse/tests/regression/validate_test_syntax.py +179 -0
- contextsynapse/tests/test_advanced_features.py +347 -0
- contextsynapse/tests/test_aiql_summary.py +283 -0
- contextsynapse/tests/test_all_aiql_queries.py +948 -0
- contextsynapse/tests/test_all_create_queries.py +213 -0
- contextsynapse/tests/test_api_vs_native.py +280 -0
- contextsynapse/tests/test_chunking_dedup.py +199 -0
- contextsynapse/tests/test_connectors.py +171 -0
- contextsynapse/tests/test_edges_and_match.py +202 -0
- contextsynapse/tests/test_extraction_pipeline_integration.py +581 -0
- contextsynapse/tests/test_name_property.py +224 -0
- contextsynapse/tests/test_node_edge_metadata.py +250 -0
- contextsynapse/tests/test_playground_conn.py +114 -0
- contextsynapse/tests/test_query_cache.py +213 -0
- contextsynapse/tests/test_source_policy_auth.py +348 -0
- contextsynapse/tests/test_temporal_and_domain.py +224 -0
- contextsynapse/tests/test_time_travel_e2e.py +571 -0
- contextsynapse/tests/test_traversal_and_aggregation.py +275 -0
- contextsynapse/tools/__init__.py +36 -0
- contextsynapse/tools/a2a_tools.py +106 -0
- contextsynapse/tools/cognition_tools.py +118 -0
- contextsynapse/tools/context.py +905 -0
- contextsynapse/tools/formatting.py +92 -0
- contextsynapse/tools/gateway_tools.py +186 -0
- contextsynapse/tools/graph.py +1700 -0
- contextsynapse/tools/intelligence.py +235 -0
- contextsynapse/tools/memory.py +118 -0
- contextsynapse/tools/registry.py +373 -0
- contextsynapse/tools/shield_tools.py +159 -0
- contextsynapse/tools/tasks.py +341 -0
- contextsynapse/tools/workspace_tools.py +124 -0
- contextsynapse/utils/__init__.py +15 -0
- contextsynapse/utils/config_loader.py +198 -0
- contextsynapse/utils/env_loader.py +156 -0
- contextsynapse/utils/file_utils.py +288 -0
- contextsynapse/utils/logging_optimizer.py +119 -0
- contextsynapse/vector/__init__.py +30 -0
- contextsynapse/vector/chroma_vector_store.py +152 -0
- contextsynapse/vector/custom_vector_store.py +537 -0
- contextsynapse/vector/faiss_vector_store.py +296 -0
- contextsynapse/vector/qdrant_vector_store.py +163 -0
- contextsynapse/vector/vector_db.py +953 -0
- contextsynapse/vector/vector_db_manager.py +197 -0
- contextsynapse/workspace/__init__.py +27 -0
- contextsynapse/workspace/base.py +94 -0
- contextsynapse/workspace/git.py +228 -0
- contextsynapse/workspace/github.py +78 -0
- contextsynapse/workspace/local.py +73 -0
- contextsynapse/workspace/tools.py +222 -0
- contextsynapse-1.0.0.dist-info/METADATA +847 -0
- contextsynapse-1.0.0.dist-info/RECORD +776 -0
- contextsynapse-1.0.0.dist-info/WHEEL +5 -0
- contextsynapse-1.0.0.dist-info/entry_points.txt +4 -0
- contextsynapse-1.0.0.dist-info/licenses/LICENSE +200 -0
- contextsynapse-1.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,986 @@
|
|
|
1
|
+
"""
|
|
2
|
+
AIContextDB MCP Server
|
|
3
|
+
==================
|
|
4
|
+
Exposes AIContextDB's Universal Tool Layer as MCP tools that any
|
|
5
|
+
MCP-compatible agent (Claude Code, Copilot, etc.) can use.
|
|
6
|
+
|
|
7
|
+
Two agents using this server share the SAME graph — that's the point.
|
|
8
|
+
|
|
9
|
+
Run directly:
|
|
10
|
+
python -m contextsynapse.mcp.server
|
|
11
|
+
python -m contextsynapse.mcp.server --namespace myproject
|
|
12
|
+
python -m contextsynapse.mcp.server --transport sse --port 8100
|
|
13
|
+
|
|
14
|
+
Or register with Claude Code:
|
|
15
|
+
claude mcp add contextcore -- python -m contextsynapse.mcp.server
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
import json
|
|
19
|
+
import logging
|
|
20
|
+
import os
|
|
21
|
+
import sys
|
|
22
|
+
import builtins
|
|
23
|
+
|
|
24
|
+
# ── CRITICAL: Protect stdout from stray print() calls ──────────────
|
|
25
|
+
# MCP uses stdout exclusively for JSON-RPC. Any print() from any module
|
|
26
|
+
# (logging, indexing, etc.) corrupts the protocol and crashes the server.
|
|
27
|
+
# Override builtins.print to redirect to stderr.
|
|
28
|
+
_original_print = builtins.print
|
|
29
|
+
|
|
30
|
+
def _safe_print(*args, **kwargs):
|
|
31
|
+
"""Redirect all print() to stderr to protect MCP's stdout."""
|
|
32
|
+
kwargs['file'] = kwargs.get('file', sys.stderr)
|
|
33
|
+
if kwargs['file'] is sys.stdout:
|
|
34
|
+
kwargs['file'] = sys.stderr
|
|
35
|
+
_original_print(*args, **kwargs)
|
|
36
|
+
|
|
37
|
+
builtins.print = _safe_print
|
|
38
|
+
|
|
39
|
+
# ── CRITICAL: Force ALL logging to stderr BEFORE any imports ────────
|
|
40
|
+
# Replace stdout with a stderr wrapper so even modules that add
|
|
41
|
+
# StreamHandler(sys.stdout) end up writing to stderr.
|
|
42
|
+
_real_stdout = sys.stdout
|
|
43
|
+
sys.stdout = sys.stderr # Temporarily redirect stdout to stderr for imports
|
|
44
|
+
|
|
45
|
+
from mcp.server.fastmcp import FastMCP
|
|
46
|
+
|
|
47
|
+
# Restore real stdout for MCP transport
|
|
48
|
+
sys.stdout = _real_stdout
|
|
49
|
+
|
|
50
|
+
# Configure logging to stderr
|
|
51
|
+
logging.basicConfig(
|
|
52
|
+
level=logging.INFO,
|
|
53
|
+
format="%(asctime)s [contextcore-mcp] %(message)s",
|
|
54
|
+
stream=sys.stderr,
|
|
55
|
+
force=True,
|
|
56
|
+
)
|
|
57
|
+
# Force ALL existing and future handlers to stderr
|
|
58
|
+
for handler in logging.root.handlers[:]:
|
|
59
|
+
if hasattr(handler, 'stream'):
|
|
60
|
+
handler.stream = sys.stderr
|
|
61
|
+
|
|
62
|
+
# Monkey-patch StreamHandler to always use stderr
|
|
63
|
+
_OrigStreamHandler = logging.StreamHandler
|
|
64
|
+
class _StderrStreamHandler(_OrigStreamHandler):
|
|
65
|
+
def __init__(self, stream=None):
|
|
66
|
+
super().__init__(sys.stderr)
|
|
67
|
+
logging.StreamHandler = _StderrStreamHandler
|
|
68
|
+
|
|
69
|
+
logger = logging.getLogger(__name__)
|
|
70
|
+
|
|
71
|
+
# ── Lazy-loaded shared state ─────────────────────────────────────────
|
|
72
|
+
_conn = None # AIContextDBConnection singleton
|
|
73
|
+
_agent_name = os.environ.get("CONTEXTSYNAPSE_AGENT_NAME") or os.environ.get("AICONTEXTDB_AGENT_NAME", "unknown")
|
|
74
|
+
_agent_id = None
|
|
75
|
+
_api_key = None
|
|
76
|
+
_registry = None
|
|
77
|
+
_resolved_session = None
|
|
78
|
+
_thread_id = None
|
|
79
|
+
_tool_context = None # ToolContext for dispatch
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def _get_registry():
|
|
83
|
+
global _registry
|
|
84
|
+
if _registry is None:
|
|
85
|
+
from contextsynapse.context.store_factory import create_agent_registry
|
|
86
|
+
_registry = create_agent_registry()
|
|
87
|
+
return _registry
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def _ensure_registered():
|
|
91
|
+
global _agent_id, _api_key
|
|
92
|
+
if _agent_id and _api_key:
|
|
93
|
+
return _agent_id, _api_key
|
|
94
|
+
try:
|
|
95
|
+
from datetime import datetime, timezone
|
|
96
|
+
registry = _get_registry()
|
|
97
|
+
agent, api_key = registry.register(
|
|
98
|
+
name=_agent_name, role="agent", platform="desktop",
|
|
99
|
+
capabilities=["read", "write"],
|
|
100
|
+
metadata={"adapter": "mcp", "registered_at": datetime.now(timezone.utc).isoformat()},
|
|
101
|
+
)
|
|
102
|
+
_agent_id = agent.agent_id
|
|
103
|
+
_api_key = api_key
|
|
104
|
+
logger.info(f"MCP agent registered: {_agent_name} (id: {_agent_id})")
|
|
105
|
+
except Exception as e:
|
|
106
|
+
logger.warning(f"Agent registration failed: {e}")
|
|
107
|
+
_agent_id = _agent_name
|
|
108
|
+
_api_key = ""
|
|
109
|
+
return _agent_id, _api_key
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def _get_conn():
|
|
113
|
+
global _conn, _thread_id
|
|
114
|
+
|
|
115
|
+
# Multi-session mode: check ContextVar first
|
|
116
|
+
from .session_context import get_session_scope
|
|
117
|
+
scope = get_session_scope()
|
|
118
|
+
if scope is not None:
|
|
119
|
+
if scope.conn is not None:
|
|
120
|
+
return scope.conn
|
|
121
|
+
# Build connection for this session scope
|
|
122
|
+
conn = _build_conn_for_namespace(scope.graph_namespace)
|
|
123
|
+
if conn:
|
|
124
|
+
conn._fan_out_graphs = scope.fan_out_graphs
|
|
125
|
+
scope.conn = conn
|
|
126
|
+
return conn
|
|
127
|
+
|
|
128
|
+
# Stdio single-session mode: use module globals (backward compat)
|
|
129
|
+
if _conn is None:
|
|
130
|
+
project_root = os.environ.get(
|
|
131
|
+
"AICONTEXTDB_PROJECT_ROOT",
|
|
132
|
+
os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..")),
|
|
133
|
+
)
|
|
134
|
+
if project_root not in sys.path:
|
|
135
|
+
sys.path.insert(0, project_root)
|
|
136
|
+
|
|
137
|
+
if _resolved_session:
|
|
138
|
+
namespace = _resolved_session.graph_namespace
|
|
139
|
+
_thread_id = _resolved_session.thread_id
|
|
140
|
+
else:
|
|
141
|
+
namespace = os.environ.get("CONTEXTSYNAPSE_NAMESPACE") or os.environ.get("AICONTEXTDB_NAMESPACE", "default")
|
|
142
|
+
|
|
143
|
+
# Use Redis-backed connection if Redis URL is available
|
|
144
|
+
redis_url = os.environ.get("CONTEXTSYNAPSE_REDIS_URL") or os.environ.get("AICONTEXTDB_REDIS_URL")
|
|
145
|
+
if redis_url:
|
|
146
|
+
try:
|
|
147
|
+
from contextsynapse.core.registry import GraphRegistry
|
|
148
|
+
reg = GraphRegistry()
|
|
149
|
+
db = reg.get_graph(namespace, load_if_missing=True)
|
|
150
|
+
if db:
|
|
151
|
+
# Wrap the AIContextDB instance as an AIContextDBConnection
|
|
152
|
+
from contextsynapse.adapters._base import AIContextDBConnection
|
|
153
|
+
_conn = AIContextDBConnection(namespace=namespace)
|
|
154
|
+
# Override the connection's db with the Redis-backed one
|
|
155
|
+
_conn.db = db
|
|
156
|
+
_conn._namespace = namespace
|
|
157
|
+
# Set up executor for AIQL queries
|
|
158
|
+
try:
|
|
159
|
+
from contextsynapse.aiql import AIQLExecutor
|
|
160
|
+
_conn.executor = AIQLExecutor(contextcore=db)
|
|
161
|
+
except Exception:
|
|
162
|
+
pass
|
|
163
|
+
logger.info(f"Connected via Redis registry (namespace: {namespace}, "
|
|
164
|
+
f"nodes: {len(db.get_all_nodes())})")
|
|
165
|
+
else:
|
|
166
|
+
logger.warning(f"Graph '{namespace}' not in Redis registry, falling back to file")
|
|
167
|
+
from contextsynapse.adapters._base import AIContextDBConnection
|
|
168
|
+
_conn = AIContextDBConnection(namespace=namespace)
|
|
169
|
+
except Exception as e:
|
|
170
|
+
logger.warning(f"Redis connection failed: {e}, falling back to file")
|
|
171
|
+
from contextsynapse.adapters._base import AIContextDBConnection
|
|
172
|
+
_conn = AIContextDBConnection(namespace=namespace)
|
|
173
|
+
else:
|
|
174
|
+
from contextsynapse.adapters._base import AIContextDBConnection
|
|
175
|
+
daemon_url = os.environ.get("CONTEXTSYNAPSE_DAEMON_URL") or os.environ.get("AICONTEXTDB_DAEMON_URL")
|
|
176
|
+
_conn = AIContextDBConnection(namespace=namespace, daemon_url=daemon_url)
|
|
177
|
+
|
|
178
|
+
# Attach fan-out search capability for session-based connections
|
|
179
|
+
if _conn and _resolved_session:
|
|
180
|
+
_setup_fan_out(_conn, _resolved_session.session_id)
|
|
181
|
+
elif _conn:
|
|
182
|
+
# Namespace mode — check if this namespace is a session's runtime graph
|
|
183
|
+
_setup_fan_out_by_namespace(_conn, namespace)
|
|
184
|
+
|
|
185
|
+
if not _resolved_session:
|
|
186
|
+
_ensure_registered()
|
|
187
|
+
logger.info(f"AIContextDB connection ready (namespace: {namespace}, agent: {_agent_name})")
|
|
188
|
+
return _conn
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def _build_conn_for_namespace(namespace: str):
|
|
192
|
+
"""Build an AIContextDBConnection for a given namespace. Used by both single and multi-session modes."""
|
|
193
|
+
redis_url = os.environ.get("CONTEXTSYNAPSE_REDIS_URL") or os.environ.get("AICONTEXTDB_REDIS_URL")
|
|
194
|
+
if redis_url:
|
|
195
|
+
try:
|
|
196
|
+
from contextsynapse.core.registry import GraphRegistry
|
|
197
|
+
reg = GraphRegistry()
|
|
198
|
+
db = reg.get_graph(namespace, load_if_missing=True)
|
|
199
|
+
if db:
|
|
200
|
+
from contextsynapse.adapters._base import AIContextDBConnection
|
|
201
|
+
conn = AIContextDBConnection(namespace=namespace)
|
|
202
|
+
conn.db = db
|
|
203
|
+
conn._namespace = namespace
|
|
204
|
+
try:
|
|
205
|
+
from contextsynapse.aiql import AIQLExecutor
|
|
206
|
+
conn.executor = AIQLExecutor(contextcore=db)
|
|
207
|
+
except Exception:
|
|
208
|
+
pass
|
|
209
|
+
return conn
|
|
210
|
+
except Exception:
|
|
211
|
+
pass
|
|
212
|
+
from contextsynapse.adapters._base import AIContextDBConnection
|
|
213
|
+
return AIContextDBConnection(namespace=namespace)
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
def _setup_fan_out(conn, session_id: str):
|
|
217
|
+
"""Attach fan-out search to a connection so it searches across attached graphs."""
|
|
218
|
+
try:
|
|
219
|
+
from contextsynapse.context.session import ContextSessionManager
|
|
220
|
+
from contextsynapse.core.registry import GraphRegistry
|
|
221
|
+
|
|
222
|
+
sm = ContextSessionManager(graph_registry=GraphRegistry())
|
|
223
|
+
attached = sm.get_attached_contexts(session_id)
|
|
224
|
+
if not attached:
|
|
225
|
+
return
|
|
226
|
+
|
|
227
|
+
extra_dbs = []
|
|
228
|
+
reg = GraphRegistry()
|
|
229
|
+
for ctx_ref in attached:
|
|
230
|
+
ctx_ns = ctx_ref.get("graph_namespace", "")
|
|
231
|
+
if ctx_ns:
|
|
232
|
+
ctx_db = reg.get_graph(ctx_ns, load_if_missing=True)
|
|
233
|
+
if ctx_db:
|
|
234
|
+
extra_dbs.append((ctx_ns, ctx_db))
|
|
235
|
+
logger.info(f"Fan-out: attached graph '{ctx_ns}' ({ctx_ref.get('name', '?')})")
|
|
236
|
+
|
|
237
|
+
if extra_dbs:
|
|
238
|
+
conn._fan_out_graphs = extra_dbs
|
|
239
|
+
except Exception as e:
|
|
240
|
+
logger.debug(f"Fan-out setup failed: {e}")
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
def _setup_fan_out_by_namespace(conn, namespace: str):
|
|
244
|
+
"""For namespace mode: check if any session uses this graph and attach fan-out."""
|
|
245
|
+
try:
|
|
246
|
+
from contextsynapse.context.session import ContextSessionManager
|
|
247
|
+
from contextsynapse.core.registry import GraphRegistry
|
|
248
|
+
|
|
249
|
+
sm = ContextSessionManager(graph_registry=GraphRegistry())
|
|
250
|
+
# Find session that uses this namespace as runtime graph
|
|
251
|
+
for session in sm.list_sessions():
|
|
252
|
+
if session.graph_namespace == namespace:
|
|
253
|
+
_setup_fan_out(conn, session.session_id)
|
|
254
|
+
return
|
|
255
|
+
except Exception:
|
|
256
|
+
pass
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
def _get_tool_context():
|
|
260
|
+
"""Build or return the ToolContext for dispatching tools."""
|
|
261
|
+
global _tool_context
|
|
262
|
+
from contextsynapse.tools import ToolContext
|
|
263
|
+
|
|
264
|
+
# Multi-session mode: build context from session scope
|
|
265
|
+
from .session_context import get_session_scope
|
|
266
|
+
scope = get_session_scope()
|
|
267
|
+
if scope is not None:
|
|
268
|
+
if scope.tool_context is not None:
|
|
269
|
+
return scope.tool_context
|
|
270
|
+
conn = _get_conn() # Will use scope.conn via context var
|
|
271
|
+
# Build runtime connection for agent-produced work
|
|
272
|
+
rt_ns = scope.runtime_namespace or f"{scope.graph_namespace}_rt"
|
|
273
|
+
if scope.runtime_conn is None:
|
|
274
|
+
scope.runtime_conn = _build_conn_for_namespace(rt_ns)
|
|
275
|
+
ctx = ToolContext(
|
|
276
|
+
conn=conn,
|
|
277
|
+
runtime_conn=scope.runtime_conn,
|
|
278
|
+
agent_id=scope.agent_id or "unknown",
|
|
279
|
+
agent_name=scope.agent_name,
|
|
280
|
+
thread_id=scope.thread_id or "",
|
|
281
|
+
)
|
|
282
|
+
ctx._access_level = scope.access_level
|
|
283
|
+
# Attach project — tasks/findings go to the runtime graph, not the atomic context
|
|
284
|
+
try:
|
|
285
|
+
from contextsynapse.project.graph import ProjectGraph
|
|
286
|
+
ctx.project = ProjectGraph(rt_ns, connection=scope.runtime_conn)
|
|
287
|
+
except Exception:
|
|
288
|
+
pass
|
|
289
|
+
scope.tool_context = ctx
|
|
290
|
+
return ctx
|
|
291
|
+
|
|
292
|
+
# Stdio single-session mode: use module globals
|
|
293
|
+
conn = _get_conn()
|
|
294
|
+
|
|
295
|
+
# Build runtime connection for agent-produced work
|
|
296
|
+
base_ns = conn.namespace if hasattr(conn, 'namespace') else (
|
|
297
|
+
getattr(conn, '_namespace', '') or 'default')
|
|
298
|
+
rt_ns = f"{base_ns}_rt"
|
|
299
|
+
if _resolved_session and getattr(_resolved_session, 'runtime_namespace', ''):
|
|
300
|
+
rt_ns = _resolved_session.runtime_namespace
|
|
301
|
+
rt_conn = _build_conn_for_namespace(rt_ns)
|
|
302
|
+
|
|
303
|
+
_tool_context = ToolContext(
|
|
304
|
+
conn=conn,
|
|
305
|
+
runtime_conn=rt_conn,
|
|
306
|
+
agent_id=_agent_id or "unknown",
|
|
307
|
+
agent_name=_agent_name,
|
|
308
|
+
thread_id=_thread_id or "",
|
|
309
|
+
)
|
|
310
|
+
|
|
311
|
+
# Attach project — tasks/findings go to the runtime graph, not the atomic context
|
|
312
|
+
try:
|
|
313
|
+
from contextsynapse.project.team_tools import get_project
|
|
314
|
+
_tool_context.project = get_project()
|
|
315
|
+
except Exception:
|
|
316
|
+
try:
|
|
317
|
+
from contextsynapse.project.graph import ProjectGraph
|
|
318
|
+
_tool_context.project = ProjectGraph(rt_ns, connection=rt_conn)
|
|
319
|
+
except Exception:
|
|
320
|
+
pass
|
|
321
|
+
|
|
322
|
+
return _tool_context
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
_DEFAULT_BASE_PATH = "contextcore_data"
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
# Valid edge labels for spec traceability (module-level so tests can import them)
|
|
329
|
+
_VALID_TRACE_LABELS: frozenset = frozenset([
|
|
330
|
+
"IMPLEMENTED_BY", "VERIFIED_BY", "COVERS", "REFINES", "CONSTRAINED_BY",
|
|
331
|
+
"PRESERVES", "STRANGLES", "REPLACES",
|
|
332
|
+
])
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
def _load_code_context(project_name: str):
|
|
336
|
+
"""Load a CodeContext instance for the given project name.
|
|
337
|
+
|
|
338
|
+
Returns None if the project cannot be found or loaded.
|
|
339
|
+
Used by the spec-driven MCP tools.
|
|
340
|
+
"""
|
|
341
|
+
try:
|
|
342
|
+
from contextsynapse.project.code_context import CodeContext
|
|
343
|
+
return CodeContext.load(project_name)
|
|
344
|
+
except Exception:
|
|
345
|
+
return None
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
def _warmup_embedding() -> None:
|
|
349
|
+
"""Start embedding model warmup in a background daemon thread.
|
|
350
|
+
|
|
351
|
+
Ollama loads the model on first embed_text() call (3-5s). By triggering
|
|
352
|
+
get_session_vector_store() at server startup in a daemon thread, the model
|
|
353
|
+
is already warm when the first agent calls orient().
|
|
354
|
+
"""
|
|
355
|
+
import threading as _threading
|
|
356
|
+
|
|
357
|
+
def _do_warmup():
|
|
358
|
+
try:
|
|
359
|
+
from contextsynapse.context.vector_integration import get_session_vector_store
|
|
360
|
+
get_session_vector_store()
|
|
361
|
+
except Exception:
|
|
362
|
+
pass # warmup is best-effort — never crash the server
|
|
363
|
+
|
|
364
|
+
t = _threading.Thread(target=_do_warmup, daemon=True)
|
|
365
|
+
t.start()
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
# =====================================================================
|
|
369
|
+
# MCP Server Definition
|
|
370
|
+
# =====================================================================
|
|
371
|
+
|
|
372
|
+
def _auto_capture_fn(tool_name, params, result, ctx):
|
|
373
|
+
"""Auto-capture tool call for conversation tracking."""
|
|
374
|
+
try:
|
|
375
|
+
from contextsynapse.agents.auto_capture import capture_tool_call
|
|
376
|
+
capture_tool_call(
|
|
377
|
+
agent_name=ctx.agent_name if hasattr(ctx, 'agent_name') else _agent_name,
|
|
378
|
+
agent_id=ctx.agent_id if hasattr(ctx, 'agent_id') else (_agent_id or "unknown"),
|
|
379
|
+
tool_name=tool_name,
|
|
380
|
+
params=params,
|
|
381
|
+
result=str(result)[:200],
|
|
382
|
+
namespace=ctx.conn._namespace if hasattr(ctx.conn, '_namespace') else "",
|
|
383
|
+
)
|
|
384
|
+
except Exception:
|
|
385
|
+
pass # Never let capture errors break tool execution
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
def _make_mcp_wrapper(tool_def):
|
|
389
|
+
"""Create a wrapper function with EXPLICIT named parameters for FastMCP.
|
|
390
|
+
|
|
391
|
+
FastMCP inspects function signatures to generate tool schemas.
|
|
392
|
+
Using **kwargs produces a single 'kwargs' parameter in the schema,
|
|
393
|
+
which breaks everything. Instead, we dynamically create a function
|
|
394
|
+
with the exact parameter names the tool expects.
|
|
395
|
+
"""
|
|
396
|
+
from contextsynapse.tools import ToolRegistry
|
|
397
|
+
import inspect
|
|
398
|
+
|
|
399
|
+
tool_name = tool_def.name
|
|
400
|
+
params = tool_def.params
|
|
401
|
+
|
|
402
|
+
if len(params) == 0:
|
|
403
|
+
def wrapper() -> str:
|
|
404
|
+
ctx = _get_tool_context()
|
|
405
|
+
return ToolRegistry.dispatch(tool_name, ctx, {})
|
|
406
|
+
wrapper.__name__ = tool_name
|
|
407
|
+
wrapper.__doc__ = tool_def.description
|
|
408
|
+
return wrapper
|
|
409
|
+
|
|
410
|
+
# Build a wrapper with explicit parameter names using exec
|
|
411
|
+
# This is the only way to create a function with dynamic parameter names
|
|
412
|
+
# that FastMCP can inspect via signature introspection.
|
|
413
|
+
param_parts = []
|
|
414
|
+
for p in params:
|
|
415
|
+
default = '""' if not p.required else None
|
|
416
|
+
if hasattr(p, 'default') and p.default not in (None, type(None)):
|
|
417
|
+
from contextsynapse.tools.registry import _MISSING
|
|
418
|
+
if p.default is not _MISSING:
|
|
419
|
+
default = repr(str(p.default))
|
|
420
|
+
if default is not None:
|
|
421
|
+
param_parts.append(f'{p.name}: str = {default}')
|
|
422
|
+
else:
|
|
423
|
+
param_parts.append(f'{p.name}: str')
|
|
424
|
+
|
|
425
|
+
param_str = ", ".join(param_parts)
|
|
426
|
+
param_names = [p.name for p in params]
|
|
427
|
+
dict_build = ", ".join(f'"{p}": {p}' for p in param_names)
|
|
428
|
+
|
|
429
|
+
# Write tools require write access
|
|
430
|
+
_WRITE_TOOLS = {"add_knowledge", "add_decision", "add_task", "add_relationship",
|
|
431
|
+
"complete_task", "claim_task", "handoff_task", "log_action",
|
|
432
|
+
"remember", "update_memory", "dispatch_goal", "init_project",
|
|
433
|
+
"ws_write_file", "ws_commit", "ws_push"}
|
|
434
|
+
is_write = tool_name in _WRITE_TOOLS
|
|
435
|
+
|
|
436
|
+
func_code = f'''
|
|
437
|
+
def {tool_name}({param_str}) -> str:
|
|
438
|
+
"""{tool_def.description}"""
|
|
439
|
+
ctx = _get_tool_context()
|
|
440
|
+
# Write-access control
|
|
441
|
+
if {is_write} and hasattr(ctx, "_access_level") and ctx._access_level == "read":
|
|
442
|
+
return "Error: Read-only access. You do not have write permission for this session."
|
|
443
|
+
params = {{{dict_build}}}
|
|
444
|
+
# Remove empty optional params
|
|
445
|
+
params = {{k: v for k, v in params.items() if v != ""}}
|
|
446
|
+
result = ToolRegistry.dispatch("{tool_name}", ctx, params)
|
|
447
|
+
# Auto-capture agent activity
|
|
448
|
+
_auto_capture("{tool_name}", params, result, ctx)
|
|
449
|
+
return result
|
|
450
|
+
'''
|
|
451
|
+
|
|
452
|
+
local_ns = {
|
|
453
|
+
'_get_tool_context': _get_tool_context,
|
|
454
|
+
'ToolRegistry': ToolRegistry,
|
|
455
|
+
'_auto_capture': _auto_capture_fn,
|
|
456
|
+
}
|
|
457
|
+
exec(func_code, local_ns)
|
|
458
|
+
wrapper = local_ns[tool_name]
|
|
459
|
+
return wrapper
|
|
460
|
+
|
|
461
|
+
|
|
462
|
+
def create_mcp_server() -> FastMCP:
|
|
463
|
+
"""Create and return the AIContextDB MCP server with all tools.
|
|
464
|
+
|
|
465
|
+
Tools are loaded from the Universal Tool Registry (contextcore/tools/).
|
|
466
|
+
No inline tool definitions — everything comes from one source.
|
|
467
|
+
"""
|
|
468
|
+
# Import tools to trigger registration
|
|
469
|
+
import contextsynapse.tools # noqa: F401
|
|
470
|
+
from contextsynapse.tools import ToolRegistry
|
|
471
|
+
|
|
472
|
+
mcp = FastMCP(
|
|
473
|
+
"contextsynapse",
|
|
474
|
+
instructions=(
|
|
475
|
+
"AIContextDB is a shared graph database for AI agent collaboration. "
|
|
476
|
+
"You have tools to: add knowledge nodes, search nodes, create relationships, "
|
|
477
|
+
"build LLM context, and manage tasks. "
|
|
478
|
+
"START HERE: Call orient() first to see what data exists, your tasks, and team status. "
|
|
479
|
+
"Use the high-level tools (add_knowledge, search_nodes, claim_task, complete_task) "
|
|
480
|
+
"for most work. Use query_graph only for advanced queries. "
|
|
481
|
+
"Everything you write is visible to other agents."
|
|
482
|
+
),
|
|
483
|
+
)
|
|
484
|
+
|
|
485
|
+
# Warm up the embedding model in the background so first orient() is fast
|
|
486
|
+
_warmup_embedding()
|
|
487
|
+
|
|
488
|
+
# Register ALL tools from the Universal Tool Registry
|
|
489
|
+
for tool_def in ToolRegistry.all():
|
|
490
|
+
wrapper = _make_mcp_wrapper(tool_def)
|
|
491
|
+
mcp.add_tool(wrapper, name=tool_def.name, description=tool_def.description)
|
|
492
|
+
|
|
493
|
+
logger.info(f"MCP server created with {ToolRegistry.count()} tools from Universal Registry")
|
|
494
|
+
|
|
495
|
+
# ── MCP-only extras (not in universal registry) ─────────────────
|
|
496
|
+
|
|
497
|
+
# Extraction tools (MCP-only for now — depend on LLM client)
|
|
498
|
+
@mcp.tool()
|
|
499
|
+
def extract_entities(text: str, provider: str = "", model: str = "") -> str:
|
|
500
|
+
"""Extract named entities from text using LLM."""
|
|
501
|
+
conn = _get_conn()
|
|
502
|
+
try:
|
|
503
|
+
from contextsynapse.extraction import extract_engine
|
|
504
|
+
result = extract_engine.extract_entities(
|
|
505
|
+
text, conn=conn, provider=provider or None, model=model or None,
|
|
506
|
+
)
|
|
507
|
+
return json.dumps(result, indent=2, default=str)[:3000]
|
|
508
|
+
except Exception as e:
|
|
509
|
+
return f"Error: {e}"
|
|
510
|
+
|
|
511
|
+
@mcp.tool()
|
|
512
|
+
def extract_facts(text: str, provider: str = "", model: str = "") -> str:
|
|
513
|
+
"""Extract facts/claims from text using LLM."""
|
|
514
|
+
conn = _get_conn()
|
|
515
|
+
try:
|
|
516
|
+
from contextsynapse.extraction import extract_engine
|
|
517
|
+
result = extract_engine.extract_facts(
|
|
518
|
+
text, conn=conn, provider=provider or None, model=model or None,
|
|
519
|
+
)
|
|
520
|
+
return json.dumps(result, indent=2, default=str)[:3000]
|
|
521
|
+
except Exception as e:
|
|
522
|
+
return f"Error: {e}"
|
|
523
|
+
|
|
524
|
+
@mcp.tool()
|
|
525
|
+
def extract_with_schema(text: str, schema_path: str, provider: str = "", model: str = "") -> str:
|
|
526
|
+
"""Extract entities using a YAML schema file."""
|
|
527
|
+
conn = _get_conn()
|
|
528
|
+
try:
|
|
529
|
+
from contextsynapse.extraction import extract_engine
|
|
530
|
+
result = extract_engine.extract_with_schema(
|
|
531
|
+
text, schema_path=schema_path, conn=conn,
|
|
532
|
+
provider=provider or None, model=model or None,
|
|
533
|
+
)
|
|
534
|
+
return json.dumps(result, indent=2, default=str)[:3000]
|
|
535
|
+
except Exception as e:
|
|
536
|
+
return f"Error: {e}"
|
|
537
|
+
|
|
538
|
+
@mcp.tool()
|
|
539
|
+
def save_schema(schema_path: str) -> str:
|
|
540
|
+
"""Upload a YAML schema to the registry."""
|
|
541
|
+
conn = _get_conn()
|
|
542
|
+
try:
|
|
543
|
+
from contextsynapse.extraction import extract_engine
|
|
544
|
+
result = extract_engine.save_schema(schema_path, conn=conn)
|
|
545
|
+
return result
|
|
546
|
+
except Exception as e:
|
|
547
|
+
return f"Error: {e}"
|
|
548
|
+
|
|
549
|
+
@mcp.tool()
|
|
550
|
+
def list_schemas() -> str:
|
|
551
|
+
"""List all saved schemas in the registry."""
|
|
552
|
+
conn = _get_conn()
|
|
553
|
+
try:
|
|
554
|
+
from contextsynapse.extraction import extract_engine
|
|
555
|
+
result = extract_engine.list_schemas(conn=conn)
|
|
556
|
+
return result
|
|
557
|
+
except Exception as e:
|
|
558
|
+
return f"Error: {e}"
|
|
559
|
+
|
|
560
|
+
@mcp.tool()
|
|
561
|
+
def extract_with_saved_schema(text: str, schema_name: str, provider: str = "", model: str = "") -> str:
|
|
562
|
+
"""Extract entities using a schema from the registry."""
|
|
563
|
+
conn = _get_conn()
|
|
564
|
+
try:
|
|
565
|
+
from contextsynapse.extraction import extract_engine
|
|
566
|
+
result = extract_engine.extract_with_saved_schema(
|
|
567
|
+
text, schema_name=schema_name, conn=conn,
|
|
568
|
+
provider=provider or None, model=model or None,
|
|
569
|
+
)
|
|
570
|
+
return json.dumps(result, indent=2, default=str)[:3000]
|
|
571
|
+
except Exception as e:
|
|
572
|
+
return f"Error: {e}"
|
|
573
|
+
|
|
574
|
+
# Project tools (SDLC context namespaces)
|
|
575
|
+
@mcp.tool()
|
|
576
|
+
def create_project(name: str) -> str:
|
|
577
|
+
"""Create an SDLC context project namespace."""
|
|
578
|
+
if not name:
|
|
579
|
+
return "Error: name is required."
|
|
580
|
+
try:
|
|
581
|
+
from contextsynapse.project.project_context import ProjectContext
|
|
582
|
+
pc = ProjectContext.create(name, base_path=_DEFAULT_BASE_PATH)
|
|
583
|
+
return f"Project '{pc.name}' created. Use coverage_score to check context coverage."
|
|
584
|
+
except Exception as e:
|
|
585
|
+
return f"Error: {e}"
|
|
586
|
+
|
|
587
|
+
@mcp.tool()
|
|
588
|
+
def add_sdlc_node(
|
|
589
|
+
project_name: str,
|
|
590
|
+
node_type: str,
|
|
591
|
+
node_id: str,
|
|
592
|
+
properties: str = "{}",
|
|
593
|
+
) -> str:
|
|
594
|
+
"""Add a typed SDLC artifact node to a project namespace.
|
|
595
|
+
|
|
596
|
+
Args:
|
|
597
|
+
project_name: the project namespace name (must exist)
|
|
598
|
+
node_type: one of the 15 SDLC types — Requirement, UserStory, Goal,
|
|
599
|
+
ArchDecision, Pattern, Constraint, CodeModule, APIContract,
|
|
600
|
+
DataModel, TestCase, TestResult, KnownIssue,
|
|
601
|
+
Preservation, Migration, ChangeRecord
|
|
602
|
+
node_id: unique node identifier within the project (e.g. "req:auth-login")
|
|
603
|
+
properties: JSON object of node properties (must include required fields
|
|
604
|
+
for the node_type — check validate_node for details)
|
|
605
|
+
"""
|
|
606
|
+
if not project_name:
|
|
607
|
+
return "Error: project_name is required."
|
|
608
|
+
if not node_type:
|
|
609
|
+
return "Error: node_type is required."
|
|
610
|
+
if not node_id:
|
|
611
|
+
return "Error: node_id is required."
|
|
612
|
+
try:
|
|
613
|
+
import json as _json
|
|
614
|
+
from contextsynapse.project.project_context import ProjectContext
|
|
615
|
+
from contextsynapse.project.sdlc_schema import is_sdlc_node_type, validate_node, ALL_NODE_TYPES
|
|
616
|
+
from contextsynapse.core.graph_structures import GraphNode
|
|
617
|
+
|
|
618
|
+
if not is_sdlc_node_type(node_type):
|
|
619
|
+
return (
|
|
620
|
+
f"Error: '{node_type}' is not a valid SDLC node type. "
|
|
621
|
+
f"Valid types: {', '.join(ALL_NODE_TYPES)}"
|
|
622
|
+
)
|
|
623
|
+
|
|
624
|
+
try:
|
|
625
|
+
props = _json.loads(properties) if properties else {}
|
|
626
|
+
except _json.JSONDecodeError as exc:
|
|
627
|
+
return f"Error: properties is not valid JSON — {exc}"
|
|
628
|
+
|
|
629
|
+
missing = validate_node(node_type, props)
|
|
630
|
+
if missing:
|
|
631
|
+
return (
|
|
632
|
+
f"Error: node_type '{node_type}' is missing required fields: "
|
|
633
|
+
f"{', '.join(missing)}"
|
|
634
|
+
)
|
|
635
|
+
|
|
636
|
+
pc = ProjectContext.load(project_name, base_path=_DEFAULT_BASE_PATH)
|
|
637
|
+
existing = pc.db.get_node(node_id)
|
|
638
|
+
if existing is not None:
|
|
639
|
+
return _json.dumps({
|
|
640
|
+
"ok": False,
|
|
641
|
+
"error": "conflict",
|
|
642
|
+
"node_id": node_id,
|
|
643
|
+
"existing_label": existing.label,
|
|
644
|
+
"hint": "Use a different node_id or update the existing node.",
|
|
645
|
+
})
|
|
646
|
+
pc.db.add_node(GraphNode(id=node_id, label=node_type, properties=props))
|
|
647
|
+
return _json.dumps({"ok": True, "node_id": node_id, "node_type": node_type})
|
|
648
|
+
except KeyError as e:
|
|
649
|
+
return f"Error: {e}"
|
|
650
|
+
except Exception as e:
|
|
651
|
+
return f"Error: {e}"
|
|
652
|
+
|
|
653
|
+
@mcp.tool()
|
|
654
|
+
def coverage_score(project_name: str) -> str:
|
|
655
|
+
"""Return per-layer SDLC coverage scores for a project namespace."""
|
|
656
|
+
if not project_name:
|
|
657
|
+
return "Error: project_name is required."
|
|
658
|
+
try:
|
|
659
|
+
from contextsynapse.project.project_context import ProjectContext
|
|
660
|
+
pc = ProjectContext.load(project_name, base_path=_DEFAULT_BASE_PATH)
|
|
661
|
+
return json.dumps(pc.coverage_score())
|
|
662
|
+
except Exception as e:
|
|
663
|
+
return f"Error: {e}"
|
|
664
|
+
|
|
665
|
+
@mcp.tool()
|
|
666
|
+
def project_stale(project_name: str) -> str:
|
|
667
|
+
"""Return all stale SDLC nodes in a project namespace."""
|
|
668
|
+
if not project_name:
|
|
669
|
+
return "Error: project_name is required."
|
|
670
|
+
try:
|
|
671
|
+
from contextsynapse.project.project_context import ProjectContext
|
|
672
|
+
pc = ProjectContext.load(project_name, base_path=_DEFAULT_BASE_PATH)
|
|
673
|
+
return json.dumps(pc.stale_report())
|
|
674
|
+
except Exception as e:
|
|
675
|
+
return f"Error: {e}"
|
|
676
|
+
|
|
677
|
+
@mcp.tool()
|
|
678
|
+
def agent_brief(project_name: str, topic: str = "", phase: str = "") -> str:
|
|
679
|
+
"""Return a scoped SDLC context package for an agent about to work.
|
|
680
|
+
|
|
681
|
+
Args:
|
|
682
|
+
project_name: the project namespace name
|
|
683
|
+
topic: keyword to filter nodes by (case-insensitive substring match)
|
|
684
|
+
phase: SDLC layer to filter to (intent/design/build/verify/evolution)
|
|
685
|
+
"""
|
|
686
|
+
if not project_name:
|
|
687
|
+
return "Error: project_name is required."
|
|
688
|
+
try:
|
|
689
|
+
from contextsynapse.project.project_context import ProjectContext
|
|
690
|
+
pc = ProjectContext.load(project_name, base_path=_DEFAULT_BASE_PATH)
|
|
691
|
+
return json.dumps(pc.agent_brief(topic=topic, phase=phase))
|
|
692
|
+
except Exception as e:
|
|
693
|
+
return f"Error: {e}"
|
|
694
|
+
|
|
695
|
+
@mcp.tool()
|
|
696
|
+
def add_sdlc_edge(
|
|
697
|
+
project_name: str,
|
|
698
|
+
edge_type: str,
|
|
699
|
+
source_id: str,
|
|
700
|
+
target_id: str,
|
|
701
|
+
) -> str:
|
|
702
|
+
"""Declare a typed relationship between two SDLC nodes in a project namespace.
|
|
703
|
+
|
|
704
|
+
Args:
|
|
705
|
+
project_name: the project namespace name (must exist)
|
|
706
|
+
edge_type: one of the 12 SDLC edge types —
|
|
707
|
+
IMPLEMENTS, SATISFIES, TESTS, GOVERNS, CONSTRAINED_BY,
|
|
708
|
+
DEPENDS_ON, EXPOSES, USES,
|
|
709
|
+
PRESERVES, STRANGLES, REPLACES, MODIFIES
|
|
710
|
+
source_id: node_id of the source node (must exist in the project)
|
|
711
|
+
target_id: node_id of the target node (must exist in the project)
|
|
712
|
+
|
|
713
|
+
The edge is validated against the schema: each edge_type has a required
|
|
714
|
+
source label and target label. Both nodes must already exist.
|
|
715
|
+
"""
|
|
716
|
+
if not project_name:
|
|
717
|
+
return "Error: project_name is required."
|
|
718
|
+
if not edge_type:
|
|
719
|
+
return "Error: edge_type is required."
|
|
720
|
+
if not source_id:
|
|
721
|
+
return "Error: source_id is required."
|
|
722
|
+
if not target_id:
|
|
723
|
+
return "Error: target_id is required."
|
|
724
|
+
try:
|
|
725
|
+
import uuid as _uuid
|
|
726
|
+
from contextsynapse.project.project_context import ProjectContext
|
|
727
|
+
from contextsynapse.project.sdlc_schema import SDLC_EDGE_TYPES
|
|
728
|
+
from contextsynapse.core.graph_structures import GraphEdge
|
|
729
|
+
|
|
730
|
+
if edge_type not in SDLC_EDGE_TYPES:
|
|
731
|
+
return (
|
|
732
|
+
f"Error: '{edge_type}' is not a valid SDLC edge type. "
|
|
733
|
+
f"Valid types: {', '.join(sorted(SDLC_EDGE_TYPES))}"
|
|
734
|
+
)
|
|
735
|
+
|
|
736
|
+
expected_src_label, expected_tgt_label = SDLC_EDGE_TYPES[edge_type]
|
|
737
|
+
|
|
738
|
+
pc = ProjectContext.load(project_name, base_path=_DEFAULT_BASE_PATH)
|
|
739
|
+
|
|
740
|
+
src_node = pc.db.get_node(source_id)
|
|
741
|
+
if src_node is None:
|
|
742
|
+
return f"Error: source node '{source_id}' not found in project '{project_name}'."
|
|
743
|
+
if src_node.label != expected_src_label:
|
|
744
|
+
return (
|
|
745
|
+
f"Error: edge type '{edge_type}' requires source label "
|
|
746
|
+
f"'{expected_src_label}', but '{source_id}' has label '{src_node.label}'."
|
|
747
|
+
)
|
|
748
|
+
|
|
749
|
+
tgt_node = pc.db.get_node(target_id)
|
|
750
|
+
if tgt_node is None:
|
|
751
|
+
return f"Error: target node '{target_id}' not found in project '{project_name}'."
|
|
752
|
+
if tgt_node.label != expected_tgt_label:
|
|
753
|
+
return (
|
|
754
|
+
f"Error: edge type '{edge_type}' requires target label "
|
|
755
|
+
f"'{expected_tgt_label}', but '{target_id}' has label '{tgt_node.label}'."
|
|
756
|
+
)
|
|
757
|
+
|
|
758
|
+
edge_id = str(_uuid.uuid4())
|
|
759
|
+
pc.db.add_edge(GraphEdge(
|
|
760
|
+
id=edge_id,
|
|
761
|
+
source=source_id,
|
|
762
|
+
target=target_id,
|
|
763
|
+
label=edge_type,
|
|
764
|
+
))
|
|
765
|
+
return json.dumps({
|
|
766
|
+
"ok": True,
|
|
767
|
+
"edge_id": edge_id,
|
|
768
|
+
"edge_type": edge_type,
|
|
769
|
+
"source_id": source_id,
|
|
770
|
+
"target_id": target_id,
|
|
771
|
+
})
|
|
772
|
+
except KeyError as e:
|
|
773
|
+
return f"Error: {e}"
|
|
774
|
+
except Exception as e:
|
|
775
|
+
return f"Error: {e}"
|
|
776
|
+
|
|
777
|
+
@mcp.tool()
|
|
778
|
+
def search_sdlc(
|
|
779
|
+
project_name: str,
|
|
780
|
+
query: str,
|
|
781
|
+
layer: str = "",
|
|
782
|
+
limit: int = 20,
|
|
783
|
+
) -> str:
|
|
784
|
+
"""Search SDLC nodes in a project namespace by keyword relevance.
|
|
785
|
+
|
|
786
|
+
Args:
|
|
787
|
+
project_name: the project namespace name (must exist)
|
|
788
|
+
query: space-separated keywords to search for
|
|
789
|
+
layer: optional SDLC layer to restrict results to —
|
|
790
|
+
intent, design, build, verify, or evolution
|
|
791
|
+
limit: max results to return (default 20, max 100)
|
|
792
|
+
|
|
793
|
+
Returns JSON list of {node_id, label, layer, score, snippet} ordered
|
|
794
|
+
by relevance. 'layer' tells you which SDLC phase each result belongs to
|
|
795
|
+
so agents can reason about coverage gaps.
|
|
796
|
+
"""
|
|
797
|
+
if not project_name:
|
|
798
|
+
return "Error: project_name is required."
|
|
799
|
+
if not query:
|
|
800
|
+
return "Error: query is required."
|
|
801
|
+
try:
|
|
802
|
+
from contextsynapse.project.project_context import ProjectContext
|
|
803
|
+
pc = ProjectContext.load(project_name, base_path=_DEFAULT_BASE_PATH)
|
|
804
|
+
results = pc.search(query=query, layer=layer, limit=min(limit, 100))
|
|
805
|
+
return json.dumps(results)
|
|
806
|
+
except (KeyError, ValueError) as e:
|
|
807
|
+
return f"Error: {e}"
|
|
808
|
+
except Exception as e:
|
|
809
|
+
return f"Error: {e}"
|
|
810
|
+
|
|
811
|
+
# Spec-driven traceability tools
|
|
812
|
+
@mcp.tool()
|
|
813
|
+
def ingest_spec(project_name: str, markdown_text: str) -> str:
|
|
814
|
+
"""Parse a markdown requirements spec and write Requirement/Feature/Constraint nodes.
|
|
815
|
+
|
|
816
|
+
Returns JSON with the list of created node IDs and count.
|
|
817
|
+
"""
|
|
818
|
+
cc = _load_code_context(project_name)
|
|
819
|
+
if cc is None:
|
|
820
|
+
return json.dumps({"error": f"Project '{project_name}' not found"})
|
|
821
|
+
ids = cc.ingest_spec(markdown_text)
|
|
822
|
+
return json.dumps({"created": ids, "count": len(ids)})
|
|
823
|
+
|
|
824
|
+
@mcp.tool()
|
|
825
|
+
def get_requirements(project_name: str) -> str:
|
|
826
|
+
"""Return all Requirement nodes for a project as JSON."""
|
|
827
|
+
cc = _load_code_context(project_name)
|
|
828
|
+
if cc is None:
|
|
829
|
+
return json.dumps({"error": f"Project '{project_name}' not found"})
|
|
830
|
+
reqs = cc.get_requirements()
|
|
831
|
+
return json.dumps(reqs, default=str)
|
|
832
|
+
|
|
833
|
+
@mcp.tool()
|
|
834
|
+
def check_coverage(project_name: str) -> str:
|
|
835
|
+
"""Analyse requirement traceability coverage for a project.
|
|
836
|
+
|
|
837
|
+
Returns JSON with keys: covered, partial, uncovered, coverage_pct, total.
|
|
838
|
+
"""
|
|
839
|
+
cc = _load_code_context(project_name)
|
|
840
|
+
if cc is None:
|
|
841
|
+
return json.dumps({"error": f"Project '{project_name}' not found"})
|
|
842
|
+
return json.dumps(cc.check_coverage())
|
|
843
|
+
|
|
844
|
+
@mcp.tool()
|
|
845
|
+
def link_artifact(
|
|
846
|
+
project_name: str, req_id: str, artifact_id: str, edge_label: str
|
|
847
|
+
) -> str:
|
|
848
|
+
"""Create a traceability edge between a requirement and an artifact.
|
|
849
|
+
|
|
850
|
+
edge_label must be one of: IMPLEMENTED_BY, VERIFIED_BY, COVERS, REFINES, CONSTRAINED_BY.
|
|
851
|
+
"""
|
|
852
|
+
if edge_label not in _VALID_TRACE_LABELS:
|
|
853
|
+
return json.dumps({"error": f"Invalid edge label '{edge_label}'. "
|
|
854
|
+
f"Must be one of: {sorted(_VALID_TRACE_LABELS)}"})
|
|
855
|
+
cc = _load_code_context(project_name)
|
|
856
|
+
if cc is None:
|
|
857
|
+
return json.dumps({"error": f"Project '{project_name}' not found"})
|
|
858
|
+
cc.link_artifact(req_id, artifact_id, edge_label)
|
|
859
|
+
return json.dumps({"ok": True, "edge": f"{req_id} --{edge_label}--> {artifact_id}"})
|
|
860
|
+
|
|
861
|
+
# Pipeline tool
|
|
862
|
+
@mcp.tool()
|
|
863
|
+
def run_pipeline(prompt: str, session_id: str = "", max_turns: int = 10) -> str:
|
|
864
|
+
"""Run a multi-agent pipeline on a session."""
|
|
865
|
+
return "Pipeline execution is available via the dashboard. Use the REST API to trigger it."
|
|
866
|
+
|
|
867
|
+
# Resource
|
|
868
|
+
@mcp.resource("contextcore://summary")
|
|
869
|
+
def resource_summary() -> str:
|
|
870
|
+
"""Current graph summary."""
|
|
871
|
+
ctx = _get_tool_context()
|
|
872
|
+
from contextsynapse.tools import ToolRegistry
|
|
873
|
+
return ToolRegistry.dispatch("graph_summary", ctx, {})
|
|
874
|
+
|
|
875
|
+
return mcp
|
|
876
|
+
|
|
877
|
+
|
|
878
|
+
# =====================================================================
|
|
879
|
+
# Entry point
|
|
880
|
+
# =====================================================================
|
|
881
|
+
|
|
882
|
+
|
|
883
|
+
def create_multi_session_app(graph_registry=None):
|
|
884
|
+
"""Create a Starlette app that serves MCP for multiple sessions.
|
|
885
|
+
|
|
886
|
+
Each session is accessed via /sessions/{session_id}/sse (or /messages).
|
|
887
|
+
Authentication happens per-connection via Bearer token.
|
|
888
|
+
|
|
889
|
+
Mount on the main FastAPI app:
|
|
890
|
+
app.mount("/mcp", create_multi_session_app(graph_registry))
|
|
891
|
+
"""
|
|
892
|
+
from .auth_middleware import MCPAuthMiddleware
|
|
893
|
+
|
|
894
|
+
server = create_mcp_server()
|
|
895
|
+
|
|
896
|
+
# Get the SSE Starlette app from FastMCP
|
|
897
|
+
try:
|
|
898
|
+
sse_app = server.sse_app()
|
|
899
|
+
except Exception:
|
|
900
|
+
# Fallback: use streamable_http_app if available
|
|
901
|
+
try:
|
|
902
|
+
sse_app = server.streamable_http_app()
|
|
903
|
+
except Exception:
|
|
904
|
+
logger.error("[MCP] Failed to create SSE/HTTP app from FastMCP")
|
|
905
|
+
from starlette.applications import Starlette
|
|
906
|
+
return Starlette()
|
|
907
|
+
|
|
908
|
+
# Wrap with auth middleware
|
|
909
|
+
app = MCPAuthMiddleware(sse_app, graph_registry=graph_registry)
|
|
910
|
+
|
|
911
|
+
logger.info("[MCP] Multi-session app created (auth + session routing)")
|
|
912
|
+
return app
|
|
913
|
+
|
|
914
|
+
|
|
915
|
+
def main():
|
|
916
|
+
"""Run the AIContextDB MCP server."""
|
|
917
|
+
import argparse
|
|
918
|
+
|
|
919
|
+
parser = argparse.ArgumentParser(description="AIContextDB MCP Server")
|
|
920
|
+
parser.add_argument("--session", default=None, help="Session ID to connect to")
|
|
921
|
+
parser.add_argument("--api-key", default=None, help="Agent API key (agent_id:secret)")
|
|
922
|
+
parser.add_argument("--namespace", default="default", help="Direct namespace (legacy)")
|
|
923
|
+
parser.add_argument("--agent-name", default=None, help="Agent display name")
|
|
924
|
+
parser.add_argument("--transport", default="stdio", choices=["stdio", "sse", "streamable-http"],
|
|
925
|
+
help="Transport: stdio (local), sse (remote), streamable-http (remote)")
|
|
926
|
+
parser.add_argument("--port", default=8100, type=int, help="Port for SSE/HTTP transport")
|
|
927
|
+
args = parser.parse_args()
|
|
928
|
+
|
|
929
|
+
global _agent_id, _api_key, _agent_name, _resolved_session
|
|
930
|
+
|
|
931
|
+
api_key = args.api_key or os.environ.get("CONTEXTSYNAPSE_API_KEY") or os.environ.get("AICONTEXTDB_API_KEY", "")
|
|
932
|
+
session_id = args.session or os.environ.get("CONTEXTSYNAPSE_SESSION_ID") or os.environ.get("AICONTEXTDB_SESSION_ID", os.environ.get("AICONTEXTDB_SESSION", ""))
|
|
933
|
+
|
|
934
|
+
if args.agent_name:
|
|
935
|
+
_agent_name = args.agent_name
|
|
936
|
+
|
|
937
|
+
# Session-based connection (preferred)
|
|
938
|
+
if session_id and api_key:
|
|
939
|
+
try:
|
|
940
|
+
from contextsynapse.context.session_resolver import resolve_session
|
|
941
|
+
resolved = resolve_session(session_id, api_key)
|
|
942
|
+
_resolved_session = resolved
|
|
943
|
+
_agent_id = resolved.agent_id
|
|
944
|
+
_agent_name = resolved.agent_name
|
|
945
|
+
_api_key = api_key.split(":", 1)[1] if ":" in api_key else ""
|
|
946
|
+
logger.info(f"Session resolved: {session_id} -> graph={resolved.graph_namespace}, "
|
|
947
|
+
f"goal='{resolved.goal}', access={resolved.access_level}")
|
|
948
|
+
except Exception as e:
|
|
949
|
+
# Retry once after 2s — Redis may not be ready on cold start
|
|
950
|
+
logger.warning(f"Session resolution attempt 1 failed: {e}, retrying...")
|
|
951
|
+
import time
|
|
952
|
+
time.sleep(2)
|
|
953
|
+
try:
|
|
954
|
+
resolved = resolve_session(session_id, api_key)
|
|
955
|
+
_resolved_session = resolved
|
|
956
|
+
_agent_id = resolved.agent_id
|
|
957
|
+
_agent_name = resolved.agent_name
|
|
958
|
+
_api_key = api_key.split(":", 1)[1] if ":" in api_key else ""
|
|
959
|
+
logger.info(f"Session resolved (retry): {session_id} -> graph={resolved.graph_namespace}")
|
|
960
|
+
except Exception as e2:
|
|
961
|
+
logger.error(f"Session resolution failed after retry: {e2}")
|
|
962
|
+
# Fall back to namespace mode instead of exiting
|
|
963
|
+
logger.info("Falling back to namespace mode: default")
|
|
964
|
+
os.environ["AICONTEXTDB_NAMESPACE"] = args.namespace
|
|
965
|
+
elif api_key:
|
|
966
|
+
if ":" in api_key:
|
|
967
|
+
_agent_id, _api_key = api_key.split(":", 1)
|
|
968
|
+
os.environ["AICONTEXTDB_NAMESPACE"] = args.namespace
|
|
969
|
+
logger.info(f"Starting in namespace mode: {args.namespace}")
|
|
970
|
+
else:
|
|
971
|
+
os.environ["AICONTEXTDB_NAMESPACE"] = args.namespace
|
|
972
|
+
logger.info(f"Starting in dev mode (no auth): {args.namespace}")
|
|
973
|
+
|
|
974
|
+
server = create_mcp_server()
|
|
975
|
+
|
|
976
|
+
if args.transport in ("sse", "streamable-http"):
|
|
977
|
+
os.environ["FASTMCP_PORT"] = str(args.port)
|
|
978
|
+
os.environ["FASTMCP_HOST"] = "0.0.0.0"
|
|
979
|
+
logger.info(f"MCP server starting on port {args.port} ({args.transport})")
|
|
980
|
+
logger.info(f"Remote agents can connect to: http://0.0.0.0:{args.port}/mcp")
|
|
981
|
+
|
|
982
|
+
server.run(transport=args.transport)
|
|
983
|
+
|
|
984
|
+
|
|
985
|
+
if __name__ == "__main__":
|
|
986
|
+
main()
|