Skip to content
Draft
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
6 changes: 5 additions & 1 deletion app-store/arxiv/arxiv_bg_worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import arxiv

from arxiv_common import get_bg_state_path, parse_research_interests
from arxiv_common import get_bg_state_path, is_background_enabled, parse_research_interests

logger = logging.getLogger("arxiv.bg_worker")
logger.setLevel(logging.INFO)
Expand Down Expand Up @@ -47,6 +47,10 @@ def verify(self) -> tuple[bool, str]:
return True, f"ArXiv background configured with {len(interests)} interest(s)."

def run_cycle(self) -> BgRunResult:
if not is_background_enabled():
logger.info("Background disabled. Skipping cycle.")
return BgRunResult(content=None)

interests = self.interests
if not interests:
return BgRunResult(error="no_interests")
Expand Down
32 changes: 31 additions & 1 deletion app-store/arxiv/arxiv_common.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
from __future__ import annotations

import json
import os
from pathlib import Path

MAX_RESULTS = 50
DEFAULT_STORAGE_PATH = Path.home() / ".arxiv-mcp-server" / "papers"
DEFAULT_BG_STATE_PATH = Path("/root/.arxiv-truffle/arxiv_bg_state.json")
DEFAULT_SETTINGS_PATH = Path("/root/.arxiv-truffle/arxiv_settings.json")


def get_storage_path() -> Path:
Expand All @@ -15,6 +17,35 @@ def get_storage_path() -> Path:
path.mkdir(parents=True, exist_ok=True)
return path

def get_settings_path() -> Path:
raw = str(os.getenv("ARXIV_SETTINGS_PATH", "")).strip()
path = Path(raw) if raw else DEFAULT_SETTINGS_PATH
path.parent.mkdir(parents=True, exist_ok=True)
return path

def load_settings() -> dict:
path = get_settings_path()
try:
if path.exists():
data = json.loads(path.read_text(encoding="utf-8"))
return data
except Exception:
pass
return {}

def save_settings(data: dict) -> None:
path = get_settings_path()
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(json.dumps(data, indent=2, sort_keys=True), encoding="utf-8")

def is_background_enabled() -> bool:
settings = load_settings()
return settings.get("background_enabled", True)

def set_background_enabled(enabled: bool) -> None:
settings = load_settings()
settings["background_enabled"] = enabled
save_settings(settings)

def get_bg_state_path() -> Path:
raw = str(os.getenv("ARXIV_BG_STATE_PATH", "")).strip()
Expand All @@ -39,4 +70,3 @@ def parse_research_interests(raw: str | None) -> list[str]:
seen.add(key)
out.append(interest)
return out

33 changes: 33 additions & 0 deletions app-store/arxiv/arxiv_foreground.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@
from truffile.app_runtime import ForegroundApp, ToolSpec, phosphor_icon_url

import arxiv_tools
from arxiv_common import is_background_enabled, set_background_enabled


class ArxivForegroundApp(ForegroundApp):
def __init__(self) -> None:
super().__init__("arxiv", logger_name="arxiv.foreground")
self._register_tools()
self._register_settings_tools()
self._register_prompts()

def _register_tools(self) -> None:
Expand Down Expand Up @@ -81,6 +83,37 @@ async def list_papers_tool() -> dict[str, Any]:
async def read_paper_tool(paper_id: str) -> dict[str, Any]:
return await arxiv_tools.read_paper(paper_id=paper_id)

def _register_settings_tools(self) -> None:
@self.tool(
ToolSpec(
name="toggle_background",
description=(
"Enable or disable background paper recommendations. "
"When disabled, the background worker skips its search cycle."
),
icon=phosphor_icon_url("toggle-right"),
)
)
async def toggle_background_tool(
enabled: bool,
) -> dict[str, Any]:
set_background_enabled(enabled)
state = "enabled" if enabled else "disabled"
return {"status": "success", "background_enabled": enabled, "message": f"Background recommendations {state}."}

@self.tool(
ToolSpec(
name="background_status",
description="Check whether background paper recommendations are currently enabled or disabled.",
icon=phosphor_icon_url("info"),
readonly=True,
)
)
async def background_status_tool() -> dict[str, Any]:
enabled = is_background_enabled()
state = "enabled" if enabled else "disabled"
return {"status": "success", "background_enabled": enabled, "message": f"Background recommendations are {state}."}

def _register_prompts(self) -> None:
@self.prompt(
"deep-paper-analysis",
Expand Down
1 change: 1 addition & 0 deletions app-store/arxiv/truffile.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,5 @@ steps:
run: |
mkdir -p /root/.arxiv-mcp-server/papers
mkdir -p /root/.arxiv-truffle
python -c 'from arxiv_common import set_background_enabled; import os; enabled = os.getenv("ARXIV_BACKGROUND_ENABLED", "true").lower() in ("true", "1", "yes"); set_background_enabled(enabled)'
echo "ArXiv MCP installation complete!"