Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ permissions:

on:
push:
branches: [ main ]
branches: [ main, devel ]
paths-ignore:
- '**/*.md'
- '**/*.jpg'
Expand All @@ -16,7 +16,7 @@ on:
- '.gitignore'
- '.python-version'
pull_request:
branches: [ main ]
branches: [ main, devel ]
paths-ignore:
- '**/*.md'
- '**/*.jpg'
Expand All @@ -31,11 +31,13 @@ on:

jobs:
test:
name: Test with Python ${{ matrix.python-version }}
runs-on: ubuntu-latest
name: Test with Python ${{ matrix.python-version }} on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
# TODO: run MacOS and Windows based on commit hints (e.g., non-trivial)
os: [ubuntu-latest, macos-latest, windows-latest]
python-version: ["3.10"]

steps:
Expand Down
13 changes: 12 additions & 1 deletion mcp_client_for_ollama/utils/constants.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
"""Constants used throughout the MCP Client for Ollama application."""

import os
import platform
from mcp.types import LATEST_PROTOCOL_VERSION

# Default Claude config file location
DEFAULT_CLAUDE_CONFIG = os.path.expanduser("~/Library/Application Support/Claude/claude_desktop_config.json")
if os.name == 'nt':
# %appdata% typically resolves as C:\Users\<USERNAME>\AppData\Roaming
APPDATA = os.environ['APPDATA']
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
APPDATA = os.environ['APPDATA']
APPDATA = os.environ.get('APPDATA', os.path.expanduser('~/AppData/Roaming'))

using .get to avoid KeyError if the envar is not present. And adding fallback just in case

CONFIG_DIR = os.path.join(APPDATA, 'Claude', 'claude_desktop_config.json')
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
CONFIG_DIR = os.path.join(APPDATA, 'Claude', 'claude_desktop_config.json')
CONFIG_DIR = os.path.join(APPDATA, 'Claude')

This suggestions avoid repeating the filename for the CONFIG_DIR.
Because in line 18 already concatenate the json filename:

DEFAULT_CLAUDE_CONFIG = os.path.join(CONFIG_DIR, "claude_desktop_config.json")

else:
CONFIG_DIR = (
os.path.expanduser("~/Library/Application Support/Claude")
if platform.system() != 'Linux'
else os.path.expanduser("~/.config/Claude")
)
DEFAULT_CLAUDE_CONFIG = os.path.join(CONFIG_DIR, "claude_desktop_config.json")

# Default config directory and filename for MCP client for Ollama
DEFAULT_CONFIG_DIR = os.path.expanduser("~/.config/ollmcp")
Expand Down
7 changes: 7 additions & 0 deletions tests/test_cleanup_race_condition.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,25 @@
even when MCP servers send notifications during the shutdown process.
"""

import sys
import unittest
import asyncio
from unittest.mock import AsyncMock, MagicMock, patch, Mock
from contextlib import AsyncExitStack
from mcp_client_for_ollama.client import MCPClient
import pytest


class TestCleanupRaceCondition(unittest.IsolatedAsyncioTestCase):
"""Test suite for stdio server cleanup race conditions."""

@pytest.mark.skipif(sys.platform == 'win32' and os.getenv('CI') == 'true',
reason="No interactive console in Windows GitHub Actions")
async def test_cleanup_handles_broken_resource_error(self):
"""Test that cleanup gracefully handles BrokenResourceError during exit."""
# Note: This fails under Windows-12 via Github Actions:
# prompt_toolkit.output.win32.NoConsoleScreenBufferError: No Windows console found.
# Are you running cmd.exe?
client = MCPClient()

# Mock the exit stack to raise BrokenResourceError on aclose()
Expand Down