quant-research-mcp 0.1.0__tar.gz

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.
Files changed (47) hide show
  1. quant_research_mcp-0.1.0/.dockerignore +18 -0
  2. quant_research_mcp-0.1.0/.github/workflows/ci.yml +44 -0
  3. quant_research_mcp-0.1.0/.github/workflows/docker.yml +45 -0
  4. quant_research_mcp-0.1.0/.github/workflows/release.yml +63 -0
  5. quant_research_mcp-0.1.0/.gitignore +34 -0
  6. quant_research_mcp-0.1.0/.mcp.json.example +13 -0
  7. quant_research_mcp-0.1.0/CONTRIBUTING.md +68 -0
  8. quant_research_mcp-0.1.0/Dockerfile +21 -0
  9. quant_research_mcp-0.1.0/LICENSE +32 -0
  10. quant_research_mcp-0.1.0/Makefile +88 -0
  11. quant_research_mcp-0.1.0/PKG-INFO +315 -0
  12. quant_research_mcp-0.1.0/README.md +284 -0
  13. quant_research_mcp-0.1.0/SECURITY.md +31 -0
  14. quant_research_mcp-0.1.0/evals/evaluation.xml +94 -0
  15. quant_research_mcp-0.1.0/manifest.json +47 -0
  16. quant_research_mcp-0.1.0/pyproject.toml +81 -0
  17. quant_research_mcp-0.1.0/quant_research_mcp/__init__.py +8 -0
  18. quant_research_mcp-0.1.0/quant_research_mcp/backtest.py +421 -0
  19. quant_research_mcp-0.1.0/quant_research_mcp/cache.py +51 -0
  20. quant_research_mcp-0.1.0/quant_research_mcp/config.py +78 -0
  21. quant_research_mcp-0.1.0/quant_research_mcp/data.py +52 -0
  22. quant_research_mcp-0.1.0/quant_research_mcp/decision.py +340 -0
  23. quant_research_mcp-0.1.0/quant_research_mcp/formatting.py +18 -0
  24. quant_research_mcp-0.1.0/quant_research_mcp/indicators.py +99 -0
  25. quant_research_mcp-0.1.0/quant_research_mcp/market.py +53 -0
  26. quant_research_mcp-0.1.0/quant_research_mcp/methods/__init__.py +48 -0
  27. quant_research_mcp-0.1.0/quant_research_mcp/methods/base.py +103 -0
  28. quant_research_mcp-0.1.0/quant_research_mcp/methods/donchian_trend.py +98 -0
  29. quant_research_mcp-0.1.0/quant_research_mcp/methods/hurst_regime.py +148 -0
  30. quant_research_mcp-0.1.0/quant_research_mcp/methods/pairs_cointegration.py +125 -0
  31. quant_research_mcp-0.1.0/quant_research_mcp/methods/rsi2_reversion.py +98 -0
  32. quant_research_mcp-0.1.0/quant_research_mcp/methods/xs_momentum.py +102 -0
  33. quant_research_mcp-0.1.0/quant_research_mcp/portfolio.py +112 -0
  34. quant_research_mcp-0.1.0/quant_research_mcp/providers/__init__.py +34 -0
  35. quant_research_mcp-0.1.0/quant_research_mcp/providers/base.py +43 -0
  36. quant_research_mcp-0.1.0/quant_research_mcp/providers/yfinance_provider.py +118 -0
  37. quant_research_mcp-0.1.0/quant_research_mcp/screener.py +65 -0
  38. quant_research_mcp-0.1.0/quant_research_mcp/server.py +721 -0
  39. quant_research_mcp-0.1.0/server.json +21 -0
  40. quant_research_mcp-0.1.0/server.py +11 -0
  41. quant_research_mcp-0.1.0/tests/conftest.py +42 -0
  42. quant_research_mcp-0.1.0/tests/test_backtest.py +75 -0
  43. quant_research_mcp-0.1.0/tests/test_decision.py +109 -0
  44. quant_research_mcp-0.1.0/tests/test_indicators.py +73 -0
  45. quant_research_mcp-0.1.0/tests/test_methods.py +90 -0
  46. quant_research_mcp-0.1.0/tests/test_portfolio.py +83 -0
  47. quant_research_mcp-0.1.0/uv.lock +1420 -0
@@ -0,0 +1,18 @@
1
+ .git
2
+ .github
3
+ .venv
4
+ venv
5
+ __pycache__
6
+ *.py[cod]
7
+ *.egg-info
8
+ .pytest_cache
9
+ .ruff_cache
10
+ .mypy_cache
11
+ dist
12
+ build
13
+ *.mcpb
14
+ .mcp.json
15
+ .DS_Store
16
+ reports
17
+ evals
18
+ tests
@@ -0,0 +1,44 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ workflow_dispatch:
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ concurrency:
13
+ group: ci-${{ github.ref }}
14
+ cancel-in-progress: true
15
+
16
+ jobs:
17
+ test:
18
+ runs-on: ubuntu-latest
19
+ strategy:
20
+ fail-fast: false
21
+ matrix:
22
+ python-version: ["3.12", "3.13"]
23
+ steps:
24
+ - uses: actions/checkout@v4
25
+
26
+ - name: Install uv
27
+ uses: astral-sh/setup-uv@v5
28
+ with:
29
+ enable-cache: true
30
+
31
+ - name: Sync dependencies
32
+ run: uv sync --python ${{ matrix.python-version }}
33
+
34
+ - name: Lint (ruff)
35
+ run: uv run ruff check .
36
+
37
+ - name: Test (offline)
38
+ run: uv run pytest tests/ -q
39
+
40
+ - name: Smoke — list the 13 tools
41
+ run: |
42
+ uv run python -c "import asyncio, server; \
43
+ names = sorted(t.name for t in asyncio.run(server.mcp.list_tools())); \
44
+ assert len(names) == 13, names; print(len(names), 'tools OK')"
@@ -0,0 +1,45 @@
1
+ name: Docker
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ tags: ["v*"]
7
+ workflow_dispatch:
8
+
9
+ permissions:
10
+ contents: read
11
+ packages: write
12
+
13
+ jobs:
14
+ build-push:
15
+ runs-on: ubuntu-latest
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+
19
+ - name: Log in to GHCR
20
+ uses: docker/login-action@v3
21
+ with:
22
+ registry: ghcr.io
23
+ username: ${{ github.actor }}
24
+ password: ${{ secrets.GITHUB_TOKEN }}
25
+
26
+ - name: Image metadata
27
+ id: meta
28
+ uses: docker/metadata-action@v5
29
+ with:
30
+ images: ghcr.io/${{ github.repository }}
31
+ tags: |
32
+ type=raw,value=latest,enable={{is_default_branch}}
33
+ type=semver,pattern={{version}}
34
+ type=semver,pattern={{major}}.{{minor}}
35
+ type=sha
36
+
37
+ - name: Build and push
38
+ uses: docker/build-push-action@v6
39
+ with:
40
+ context: .
41
+ push: true
42
+ tags: ${{ steps.meta.outputs.tags }}
43
+ labels: ${{ steps.meta.outputs.labels }}
44
+ cache-from: type=gha
45
+ cache-to: type=gha,mode=max
@@ -0,0 +1,63 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags: ["v*"]
6
+ workflow_dispatch:
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ jobs:
12
+ build:
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+ - name: Install uv
17
+ uses: astral-sh/setup-uv@v5
18
+ - name: Build sdist + wheel
19
+ run: uv build
20
+ - uses: actions/upload-artifact@v4
21
+ with:
22
+ name: dist
23
+ path: dist/
24
+
25
+ pypi-publish:
26
+ needs: build
27
+ runs-on: ubuntu-latest
28
+ # PyPI Trusted Publishing (OIDC) — no token stored. Configure the trusted
29
+ # publisher for this repo + workflow + environment on PyPI first.
30
+ environment: pypi
31
+ permissions:
32
+ id-token: write
33
+ steps:
34
+ - uses: actions/download-artifact@v4
35
+ with:
36
+ name: dist
37
+ path: dist/
38
+ - name: Publish to PyPI
39
+ uses: pypa/gh-action-pypi-publish@release/v1
40
+
41
+ bundle-and-release:
42
+ needs: build
43
+ runs-on: ubuntu-latest
44
+ permissions:
45
+ contents: write
46
+ steps:
47
+ - uses: actions/checkout@v4
48
+ - uses: actions/download-artifact@v4
49
+ with:
50
+ name: dist
51
+ path: dist/
52
+ - uses: actions/setup-node@v4
53
+ with:
54
+ node-version: "20"
55
+ - name: Pack Claude Desktop bundle (.mcpb)
56
+ run: npx -y @anthropic-ai/mcpb pack . quant-research-mcp.mcpb
57
+ - name: Create GitHub Release with artifacts
58
+ uses: softprops/action-gh-release@v2
59
+ with:
60
+ files: |
61
+ dist/*
62
+ quant-research-mcp.mcpb
63
+ generate_release_notes: true
@@ -0,0 +1,34 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.egg-info/
6
+ .eggs/
7
+ dist/
8
+ build/
9
+ wheels/
10
+
11
+ # Virtualenv / uv
12
+ .venv/
13
+ venv/
14
+ env/
15
+
16
+ # Test / lint caches
17
+ .pytest_cache/
18
+ .ruff_cache/
19
+ .mypy_cache/
20
+ .coverage
21
+ htmlcov/
22
+
23
+ # Packaging artifacts
24
+ *.mcpb
25
+
26
+ # Per-machine MCP registration (contains an absolute path). Use
27
+ # `make claude-add` / `make register`, or copy .mcp.json.example.
28
+ .mcp.json
29
+
30
+ # OS / editor
31
+ .DS_Store
32
+ *.swp
33
+ .idea/
34
+ .vscode/
@@ -0,0 +1,13 @@
1
+ {
2
+ "//": "Copy to .mcp.json (gitignored). Path-free: runs straight from GitHub via uvx. After a PyPI release you can drop the --from git+... and use the published package, or `make register` for the local checkout form.",
3
+ "mcpServers": {
4
+ "quant_research": {
5
+ "command": "uvx",
6
+ "args": [
7
+ "--from",
8
+ "git+https://github.com/FlawlessByte/quant-research-mcp",
9
+ "quant-research-mcp"
10
+ ]
11
+ }
12
+ }
13
+ }
@@ -0,0 +1,68 @@
1
+ # Contributing
2
+
3
+ Thanks for your interest. This project packages paper-backed quantitative
4
+ trading methods as MCP tools, plus a deterministic decision helper. Two hard
5
+ rules keep it trustworthy:
6
+
7
+ 1. **No LLM, no subprocess, no network inside the decision logic.** The server
8
+ supplies reproducible math; the calling agent supplies judgement. `make check`
9
+ fails the build if it finds `subprocess` or `claude -p`.
10
+ 2. **Read-only.** Tools place no orders and persist nothing. Open positions are
11
+ passed in per call.
12
+
13
+ ## Dev setup
14
+
15
+ ```bash
16
+ git clone https://github.com/FlawlessByte/quant-research-mcp
17
+ cd quant-research-mcp
18
+ make dev # uv sync + ruff
19
+ make check # ruff + 40 offline tests + no-subprocess assertion
20
+ make smoke # list the 13 tools (no network)
21
+ ```
22
+
23
+ Tests must stay **fully offline** — network is monkeypatched in `tests/`. New
24
+ tests follow the same pattern (see `tests/conftest.py`).
25
+
26
+ ## Adding a paper-backed method
27
+
28
+ The registry is built for this — one new module, one import line, nothing else
29
+ changes:
30
+
31
+ ```python
32
+ # quant_research_mcp/methods/my_paper.py
33
+ from . import register
34
+ from .base import TradingMethod, TradeSetup, DataRequirements
35
+
36
+ def analyze(daily, session, context) -> TradeSetup:
37
+ ... # compute signal, entry, stop, target
38
+
39
+ register(TradingMethod(
40
+ key="my_paper_method",
41
+ name="My Method",
42
+ paper="Author et al., Title (Year)",
43
+ paper_url="https://arxiv.org/abs/...",
44
+ regime_applicability="TRENDING",
45
+ timeframe="swing", # intraday | swing | position
46
+ data=DataRequirements(daily_period="2y"),
47
+ description="One paragraph on the mechanics.",
48
+ analyze=analyze,
49
+ ))
50
+ ```
51
+
52
+ Then add `from . import my_paper` to `quant_research_mcp/methods/__init__.py`.
53
+ It now appears in `quant_list_methods` and runs via `quant_analyze_setup`. Add a
54
+ trigger-logic test in `tests/test_methods.py` on synthetic data, and — if the
55
+ method makes entry decisions — a deterministic Q&A in `evals/evaluation.xml`.
56
+
57
+ ## Before you open a PR
58
+
59
+ - `make check` is green (ruff + tests + no-subprocess).
60
+ - New behaviour has a test; new entry logic has an eval.
61
+ - Commits use [Conventional Commits](https://www.conventionalcommits.org/)
62
+ (`feat:`, `fix:`, `docs:`, `refactor:`, `test:`, `chore:`).
63
+ - Cite the paper for any new method.
64
+
65
+ ## Not financial advice
66
+
67
+ This is research tooling. Do not add anything that places orders, gives
68
+ investment advice, or implies a guaranteed outcome.
@@ -0,0 +1,21 @@
1
+ # Containerised stdio MCP server. Run with -i so the server can read stdin:
2
+ # docker run -i --rm ghcr.io/flawlessbyte/quant-research-mcp
3
+ FROM python:3.12-slim
4
+
5
+ # uv for fast, locked installs.
6
+ COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
7
+
8
+ ENV UV_COMPILE_BYTECODE=1 \
9
+ UV_LINK_MODE=copy \
10
+ UV_PYTHON_DOWNLOADS=never
11
+
12
+ WORKDIR /app
13
+
14
+ # Install dependencies first (cached layer), then the project.
15
+ COPY pyproject.toml uv.lock README.md ./
16
+ COPY quant_research_mcp ./quant_research_mcp
17
+ COPY server.py ./
18
+ RUN uv sync --frozen --no-dev
19
+
20
+ # stdio transport: the entry point talks MCP over stdin/stdout.
21
+ ENTRYPOINT ["uv", "run", "--no-dev", "quant-research-mcp"]
@@ -0,0 +1,32 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 FlawlessByte
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
23
+ ---
24
+
25
+ ADDITIONAL NOTICE — NOT FINANCIAL ADVICE
26
+
27
+ This software is research and educational tooling. It performs quantitative
28
+ computation only and places no orders. Nothing it outputs is investment advice,
29
+ a recommendation, or a solicitation to buy or sell any security. Market data may
30
+ be delayed or inaccurate. Trading involves substantial risk of loss. You are
31
+ solely responsible for any decision you make and any capital you risk. The
32
+ authors accept no liability for trading losses or for any use of this software.
@@ -0,0 +1,88 @@
1
+ # quant_research_mcp — common tasks. Run `make help` for the list.
2
+
3
+ .DEFAULT_GOAL := help
4
+ SHELL := /bin/bash
5
+
6
+ # Absolute project dir so `make register` emits a portable client config.
7
+ PROJECT_DIR := $(shell pwd)
8
+
9
+ # GHCR image name (lowercase, per registry rules).
10
+ IMAGE := ghcr.io/flawlessbyte/quant-research-mcp
11
+
12
+ .PHONY: help install install-cli uninstall-cli dev run inspect smoke test check \
13
+ build docker-build mcpb clean register claude-add claude-remove
14
+
15
+ help: ## Show this help
16
+ @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) \
17
+ | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-14s\033[0m %s\n", $$1, $$2}'
18
+
19
+ install: ## Create the venv and install dependencies (uv sync)
20
+ uv sync
21
+
22
+ install-cli: ## Install the `quant-research-mcp` binary onto your PATH (uv tool)
23
+ # --reinstall --no-cache forces a fresh build so source edits ship even when
24
+ # the project version is unchanged (uv otherwise serves a cached wheel).
25
+ uv tool install --force --reinstall --no-cache .
26
+ @echo
27
+ @echo "Installed. Binary location:"
28
+ @command -v quant-research-mcp || { \
29
+ echo " not on PATH yet — run: uv tool update-shell (then restart your shell)"; \
30
+ echo " or add $$(uv tool dir)/../bin to PATH"; }
31
+
32
+ uninstall-cli: ## Remove the `quant-research-mcp` binary from your PATH
33
+ uv tool uninstall quant-research-mcp
34
+
35
+ dev: ## Install plus dev extras (ruff) for linting
36
+ uv sync
37
+ uv add --dev ruff
38
+
39
+ run: ## Run the MCP server over stdio
40
+ uv run python server.py
41
+
42
+ inspect: ## Launch the MCP Inspector against the server
43
+ npx @modelcontextprotocol/inspector uv run python server.py
44
+
45
+ smoke: ## Import the server and list its tools (no network)
46
+ uv run python -c "import asyncio, server; \
47
+ print('tools:', sorted(t.name for t in asyncio.run(server.mcp.list_tools())))"
48
+
49
+ test: ## Run the pytest suite (no network needed)
50
+ uv run pytest tests/ -q
51
+
52
+ check: ## Tests + lint + confirm no LLM/subprocess calls
53
+ uv run pytest tests/ -q
54
+ -uv run ruff check . 2>/dev/null || echo "ruff not installed; run 'make dev'"
55
+ @if grep -rniE 'subprocess|claude -p' --include='*.py' \
56
+ --exclude-dir=.venv --exclude-dir=__pycache__ . \
57
+ | grep -v 'no LLM, no network, no subprocess'; then \
58
+ echo "FAIL: LLM/subprocess reference found"; exit 1; \
59
+ else echo "OK: no LLM/subprocess calls"; fi
60
+
61
+ register: ## Print the stdio MCP client config block for this project
62
+ @echo '{'
63
+ @echo ' "mcpServers": {'
64
+ @echo ' "quant_research": {'
65
+ @echo ' "command": "uv",'
66
+ @echo ' "args": ["run", "python", "server.py"],'
67
+ @echo ' "cwd": "$(PROJECT_DIR)"'
68
+ @echo ' }'
69
+ @echo ' }'
70
+ @echo '}'
71
+
72
+ claude-add: ## Register this local clone with Claude Code (user scope)
73
+ claude mcp add quant_research --scope user -- uv run --directory $(PROJECT_DIR) python server.py
74
+
75
+ claude-remove: ## Remove this server from Claude Code
76
+ claude mcp remove quant_research
77
+
78
+ build: ## Build the sdist + wheel into dist/
79
+ uv build
80
+
81
+ docker-build: ## Build the Docker image locally
82
+ docker build -t $(IMAGE) .
83
+
84
+ mcpb: ## Pack a Claude Desktop .mcpb bundle
85
+ npx -y @anthropic-ai/mcpb pack . quant-research-mcp.mcpb
86
+
87
+ clean: ## Remove caches and build artifacts
88
+ rm -rf .venv __pycache__ */__pycache__ */*/__pycache__ .ruff_cache dist build *.egg-info *.mcpb