From 5a8ec704fe45c51c1211f19b5333040a69fff854 Mon Sep 17 00:00:00 2001 From: CREDO23 Date: Mon, 20 Apr 2026 21:02:21 +0200 Subject: [PATCH] feat(notion-mcp): add MCP gating in agent, indexer, and health check --- .../app/agents/new_chat/chat_deepagent.py | 29 ++++++++++++++----- .../services/notion/tool_metadata_service.py | 21 +++++++++++++- .../connector_indexers/notion_indexer.py | 12 ++++++++ 3 files changed, 54 insertions(+), 8 deletions(-) diff --git a/surfsense_backend/app/agents/new_chat/chat_deepagent.py b/surfsense_backend/app/agents/new_chat/chat_deepagent.py index ab47b49ce..6709715bd 100644 --- a/surfsense_backend/app/agents/new_chat/chat_deepagent.py +++ b/surfsense_backend/app/agents/new_chat/chat_deepagent.py @@ -285,18 +285,33 @@ async def create_surfsense_deep_agent( "llm": llm, } - # Disable Notion action tools if no Notion connector is configured + # Disable Notion action tools if no Notion connector is configured. + # When an MCP-mode connector exists, use MCP tools; otherwise use direct-API tools. modified_disabled_tools = list(disabled_tools) if disabled_tools else [] has_notion_connector = ( available_connectors is not None and "NOTION_CONNECTOR" in available_connectors ) + _notion_direct_tools = [ + "create_notion_page", + "update_notion_page", + "delete_notion_page", + ] + _notion_mcp_tools = [ + "create_notion_page_mcp", + "update_notion_page_mcp", + "delete_notion_page_mcp", + ] if not has_notion_connector: - notion_tools = [ - "create_notion_page", - "update_notion_page", - "delete_notion_page", - ] - modified_disabled_tools.extend(notion_tools) + modified_disabled_tools.extend(_notion_direct_tools) + modified_disabled_tools.extend(_notion_mcp_tools) + else: + from app.services.notion_mcp import has_mcp_notion_connector + + _use_mcp = await has_mcp_notion_connector(db_session, search_space_id) + if _use_mcp: + modified_disabled_tools.extend(_notion_direct_tools) + else: + modified_disabled_tools.extend(_notion_mcp_tools) # Disable Linear action tools if no Linear connector is configured has_linear_connector = ( diff --git a/surfsense_backend/app/services/notion/tool_metadata_service.py b/surfsense_backend/app/services/notion/tool_metadata_service.py index 097ef3461..8a58d5e62 100644 --- a/surfsense_backend/app/services/notion/tool_metadata_service.py +++ b/surfsense_backend/app/services/notion/tool_metadata_service.py @@ -227,11 +227,30 @@ class NotionToolMetadataService: async def _check_account_health(self, connector_id: int) -> bool: """Check if a Notion connector's token is still valid. - Uses a lightweight ``users.me()`` call to verify the token. + For regular connectors: uses ``users.me()`` via the Notion SDK. + For MCP-mode connectors: uses ``notion-get-self`` via the MCP adapter. Returns True if the token is expired/invalid, False if healthy. """ try: + result = await self._db_session.execute( + select(SearchSourceConnector).filter( + SearchSourceConnector.id == connector_id + ) + ) + db_connector = result.scalars().first() + if not db_connector: + return True + + if (db_connector.config or {}).get("mcp_mode"): + from app.services.notion_mcp.adapter import NotionMCPAdapter + + adapter = NotionMCPAdapter( + session=self._db_session, connector_id=connector_id + ) + health = await adapter.health_check() + return health.get("status") != "success" + connector = NotionHistoryConnector( session=self._db_session, connector_id=connector_id ) diff --git a/surfsense_backend/app/tasks/connector_indexers/notion_indexer.py b/surfsense_backend/app/tasks/connector_indexers/notion_indexer.py index 77aac795a..6a3a99b5c 100644 --- a/surfsense_backend/app/tasks/connector_indexers/notion_indexer.py +++ b/surfsense_backend/app/tasks/connector_indexers/notion_indexer.py @@ -129,6 +129,18 @@ async def index_notion_pages( f"Connector with ID {connector_id} not found or is not a Notion connector", ) + if (connector.config or {}).get("mcp_mode"): + msg = ( + f"Connector {connector_id} is an MCP-mode connector. " + "Background indexing is not supported for MCP connectors — " + "use a regular Notion connector for indexing." + ) + logger.info(msg) + await task_logger.log_task_completion( + log_entry, msg, {"skipped": True, "reason": "mcp_mode"} + ) + return 0, 0, None + if not connector.config.get("access_token") and not connector.config.get( "NOTION_INTEGRATION_TOKEN" ):