[Bug]: MCP Cognify does not hold strong reference to background tasks
Bug Description
The MCP cognify_file tool does not use the background-task and error-recording helpers already defined in cognee-mcp/src/ server.py.
It currently launches cognification with:
asyncio.create_task(_cognify_bg())
Other MCP background operations use _track_background(), which retains a strong reference to the task in _background_tasks until it completes.
Additionally, cognify_file records failures using:
_task_errors.setdefault(dataset_name, []).append((ts, str(e)))
This creates a plain, unbounded list for a dataset’s first error. The existing _record_task_error() helper instead creates a deque(maxlen=50) to prevent error history from growing indefinitely.
Therefore, cognify_file bypasses both established safeguards:
- Its background task is not tracked for the duration of execution.
- Its error history can grow beyond the configured limit.
Relevant locations:
- cognee-mcp/src/server.py:79-103
- cognee-mcp/src/server.py:1584-1594
Steps to Reproduce
- Start the Cognee MCP server.
- Configure or mock cognee_client.cognify() so that it waits long enough to inspect the running task.
- Call the cognify_file MCP tool with valid base64-encoded file content.
- Inspect the module-level _background_tasks set while cognification is running.
- Observe that the task created by cognify_file is not present in _background_tasks.
- Configure or mock cognee_client.cognify() to raise an exception.
- Clear _task_errors and call cognify_file repeatedly for the same dataset.
- Allow each background task to finish.
- Inspect _task_errors[dataset_name].
- Observe that it is a plain list and can contain more than _TASK_ERROR_HISTORY entries.
The problem is also visible directly in the implementation:
except Exception as e: ts = datetime.now(timezone.utc).isoformat() _task_errors.setdefault(dataset_name, []).append((ts, str(e)))
asyncio.create_task(_cognify_bg())
This differs from the established pattern used by other MCP operations:
_record_task_error(dataset, str(e)) _track_background(coroutine)
Expected Behavior
cognify_file should use the existing task-management and error-history helpers:
async def _cognify_bg(): with redirect_stdout(sys.stderr): try: await cognee_client.cognify(datasets=[dataset_name]) logger.info( "cognify_file: background cognify finished for '%s'.", dataset_name, ) except Exception as error: _record_task_error(dataset_name, str(error)) logger.error( "cognify_file: background cognify failed for '%s': %s", dataset_name, error, exc_info=True, )
_track_background(_cognify_bg())
The task should remain in _background_tasks while running and be removed after completion.
Failure history should be stored in a bounded deque and retain at most _TASK_ERROR_HISTORY entries per dataset.
Actual Behavior
cognify_file calls asyncio.create_task() directly, so the resulting task is not retained in _background_tasks.
When background cognification fails for a dataset without an existing error bucket, the tool creates an unbounded list:
_task_errors.setdefault(dataset_name, [])
Repeated failures can therefore cause the list to grow beyond the intended 50-entry limit.
Existing MCP tests verify that cognify_file is exposed as a tool, but do not cover its background-task lifecycle or failure- history behavior.
Environment
- OS: All platforms
- Python version: Python 3.10–3.13
- Cognee version: Current main / observed on 1.4.0-local
- Component: cognee-mcp
- MCP transport: stdio, SSE, and HTTP
- LLM Provider: Provider-independent
- Database: Database-independent
Logs/Error Messages
No specific error is emitted for the task-tracking problem.
When cognification fails, the underlying exception is logged, but the failure is stored in an unbounded list rather than the
configured bounded error buffer.Additional Context
The module already contains the required helpers:
def _track_background(coro) -> asyncio.Task: task = asyncio.create_task(coro) _background_tasks.add(task) task.add_done_callback(_background_tasks.discard) return task
def _record_task_error(dataset: str, error: str) -> None: bucket = _task_errors.setdefault( dataset, deque(maxlen=_TASK_ERROR_HISTORY), ) bucket.append((datetime.now(timezone.utc).isoformat(), error))
Other MCP background operations already use these helpers, so the fix should only require making cognify_file consistent with the existing pattern.
Regression tests should verify that:
- The cognify task is present in _background_tasks while running.
- The task is removed after completion.
- Failures create a deque, not a list.
- Error history never exceeds _TASK_ERROR_HISTORY.
- Successful and failed background cognification are both handled correctly.
Pre-submission Checklist
- I have searched existing issues to ensure this bug hasn't been reported already
- I have provided a clear and detailed description of the bug
- I have included steps to reproduce the issue
- I have included my environment details
Source: topoteretes/cognee