Skip to content

Commit c543b07

Browse files
2 parents 6edae22 + 7141df0 commit c543b07

File tree

20 files changed

+4726
-3034
lines changed

20 files changed

+4726
-3034
lines changed

.github/workflows/dev-release.yml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
name: Dev Release
2+
3+
on:
4+
push:
5+
branches:
6+
- dev
7+
8+
jobs:
9+
dev-release:
10+
runs-on: ubuntu-latest
11+
permissions:
12+
contents: read
13+
id-token: write
14+
environment: pypi
15+
16+
steps:
17+
- uses: actions/checkout@v4
18+
19+
- name: Set dev version
20+
id: version
21+
run: |
22+
BASE=$(grep -oP 'version = "\K[^"]+' pyproject.toml)
23+
DEV_VERSION="${BASE}.dev${{ github.run_number }}"
24+
echo "dev_version=$DEV_VERSION" >> $GITHUB_OUTPUT
25+
echo "Publishing $DEV_VERSION"
26+
27+
- name: Patch name and version in pyproject.toml
28+
run: |
29+
sed -i 's/name = "first-agentic-csa"/name = "first-agentic-csa-dev"/' pyproject.toml
30+
sed -i 's/version = "[^"]*"/version = "${{ steps.version.outputs.dev_version }}"/' pyproject.toml
31+
sed -i 's/first-agentic-csa = "wpilib_mcp.server:main"/first-agentic-csa = "wpilib_mcp.server:main"\nfirst-agentic-csa-dev = "wpilib_mcp.server:main"\nfirst_agentic_csa_dev = "wpilib_mcp.server:main"/' pyproject.toml
32+
33+
- name: Install uv
34+
uses: astral-sh/setup-uv@v4
35+
with:
36+
version: "latest"
37+
38+
- name: Build and publish to PyPI
39+
run: |
40+
uv build
41+
uv publish --trusted-publishing always
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
name: Rebuild Documentation Indexes
2+
3+
on:
4+
schedule:
5+
# Run every Sunday at 2:00 AM UTC
6+
- cron: "0 2 * * 0"
7+
workflow_dispatch:
8+
# Allow manual triggering
9+
inputs:
10+
plugins:
11+
description: "Plugins to rebuild (comma-separated, or 'all')"
12+
required: false
13+
default: "all"
14+
15+
jobs:
16+
rebuild:
17+
runs-on: ubuntu-latest
18+
permissions:
19+
contents: write
20+
pull-requests: write
21+
22+
steps:
23+
- uses: actions/checkout@v4
24+
with:
25+
fetch-depth: 0
26+
27+
- name: Install uv
28+
uses: astral-sh/setup-uv@v4
29+
with:
30+
version: "latest"
31+
32+
- name: Set up Python
33+
run: uv python install 3.12
34+
35+
- name: Install dependencies
36+
run: uv sync --all-extras
37+
38+
- name: Rebuild WPILib stable index
39+
run: |
40+
echo "Rebuilding WPILib stable index..."
41+
uv run python scripts/build_index.py wpilib --version stable -v
42+
continue-on-error: true
43+
44+
- name: Rebuild WPILib 2025 index
45+
run: |
46+
echo "Rebuilding WPILib 2025 index..."
47+
uv run python scripts/build_index.py wpilib --version 2025 -v
48+
continue-on-error: true
49+
50+
- name: Rebuild REV index
51+
run: |
52+
echo "Rebuilding REV index..."
53+
uv run python scripts/build_index.py rev -v
54+
continue-on-error: true
55+
56+
- name: Rebuild CTRE index
57+
run: |
58+
echo "Rebuilding CTRE index..."
59+
uv run python scripts/build_index.py ctre -v
60+
continue-on-error: true
61+
62+
- name: Rebuild PhotonVision index
63+
run: |
64+
echo "Rebuilding PhotonVision index..."
65+
uv run python scripts/build_index.py photonvision -v
66+
continue-on-error: true
67+
68+
- name: Rebuild Redux index
69+
run: |
70+
echo "Rebuilding Redux index..."
71+
uv run python scripts/build_index.py redux -v
72+
continue-on-error: true
73+
74+
- name: Check for changes
75+
id: check_changes
76+
run: |
77+
if git diff --quiet src/wpilib_mcp/plugins/*/data/*.json; then
78+
echo "changes=false" >> $GITHUB_OUTPUT
79+
echo "No changes to index files"
80+
else
81+
echo "changes=true" >> $GITHUB_OUTPUT
82+
echo "Index files have been updated"
83+
git diff --stat src/wpilib_mcp/plugins/*/data/*.json
84+
fi
85+
86+
- name: Create Pull Request
87+
if: steps.check_changes.outputs.changes == 'true'
88+
uses: peter-evans/create-pull-request@v6
89+
with:
90+
token: ${{ secrets.GITHUB_TOKEN }}
91+
commit-message: "chore: rebuild documentation indexes"
92+
title: "chore: Weekly documentation index rebuild"
93+
body: |
94+
## Automated Index Rebuild
95+
96+
This PR was automatically generated by the weekly index rebuild workflow.
97+
98+
### What changed
99+
- Rebuilt documentation indexes from upstream sources
100+
- Updated search content for all enabled plugins
101+
102+
### Vendors updated
103+
- WPILib (stable + 2025)
104+
- REV Robotics
105+
- CTRE Phoenix
106+
- PhotonVision
107+
- Redux
108+
109+
### Review checklist
110+
- [ ] Index sizes look reasonable
111+
- [ ] No unexpected file deletions
112+
- [ ] Tests pass
113+
114+
---
115+
*Generated on: ${{ github.event.repository.updated_at || 'manual trigger' }}*
116+
branch: chore/rebuild-indexes
117+
delete-branch: true
118+
labels: |
119+
automated
120+
documentation
121+
122+
- name: Summary
123+
run: |
124+
echo "## Index Rebuild Summary" >> $GITHUB_STEP_SUMMARY
125+
echo "" >> $GITHUB_STEP_SUMMARY
126+
echo "| Plugin | Pages |" >> $GITHUB_STEP_SUMMARY
127+
echo "|--------|-------|" >> $GITHUB_STEP_SUMMARY
128+
for f in src/wpilib_mcp/plugins/*/data/*.json; do
129+
plugin=$(echo $f | cut -d'/' -f4)
130+
count=$(python3 -c "import json; print(len(json.load(open('$f')).get('pages', [])))" 2>/dev/null || echo "error")
131+
echo "| $plugin | $count |" >> $GITHUB_STEP_SUMMARY
132+
done

.gitignore

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ __pycache__/
33
*.py[codz]
44
*$py.class
55

6+
.claude
7+
68
# C extensions
79
*.so
810
tmpclaude*
@@ -216,4 +218,6 @@ __marimo__/
216218
# Streamlit
217219
.streamlit/secrets.toml
218220

219-
*.pyc
221+
*.pyc
222+
223+
tmpclaude*

CLAUDE.md

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
# CLAUDE.md - Project Guide for AI Assistants
2+
3+
## Project Overview
4+
5+
**FIRST Agentic CSA** is an MCP (Model Context Protocol) server that provides intelligent documentation search across FIRST Robotics Competition (FRC) documentation. It aggregates docs from multiple vendors (WPILib, REV Robotics, CTRE Phoenix, Redux, PhotonVision) and enables natural language queries via AI assistants.
6+
7+
## Tech Stack
8+
9+
- **Language:** Python 3.11+
10+
- **Package Manager:** uv (Astral's Rust-based manager)
11+
- **Protocol:** MCP 2025-06-18 schema
12+
- **Search:** BM25 ranking via `rank-bm25`
13+
- **HTTP:** httpx with async support
14+
- **HTML Parsing:** BeautifulSoup4 + lxml
15+
- **Build:** Hatchling
16+
- **Testing:** pytest with asyncio
17+
18+
## Project Structure
19+
20+
```
21+
src/wpilib_mcp/
22+
├── server.py # MCP server entry point & tool registration
23+
├── tool_router.py # Routes tool calls to plugins
24+
├── plugin_loader.py # Plugin discovery & loading
25+
├── plugins/ # Vendor plugin implementations
26+
│ ├── base.py # PluginBase abstract class
27+
│ ├── wpilib/ # WPILib core docs
28+
│ ├── rev/ # REV Robotics (SparkMax)
29+
│ ├── ctre/ # CTRE Phoenix (TalonFX)
30+
│ ├── redux/ # Redux Robotics
31+
│ └── photonvision/ # PhotonVision
32+
└── utils/
33+
├── search.py # BM25 search indexing
34+
├── fetch.py # HTTP fetching with caching
35+
├── html.py # HTML cleaning & extraction
36+
└── indexer.py # Index management
37+
38+
tests/ # pytest test suite
39+
scripts/ # Utility scripts (index building)
40+
config.json # Runtime configuration
41+
server.json # MCP server manifest
42+
```
43+
44+
## Common Commands
45+
46+
```bash
47+
# Install dependencies
48+
uv sync --all-extras
49+
50+
# Run tests
51+
uv run pytest tests/ -v
52+
53+
# Run server locally
54+
uv run first-agentic-csa
55+
56+
# Build package
57+
uv build
58+
59+
# Build documentation indexes
60+
python scripts/build_index.py all
61+
python scripts/build_index.py wpilib --version 2025
62+
python scripts/build_index.py rev
63+
```
64+
65+
## Architecture Patterns
66+
67+
### Plugin System
68+
- Each vendor implements a Plugin class extending `PluginBase`
69+
- Plugins are loaded dynamically based on `config.json`
70+
- Lifecycle: load → initialize → search/fetch → shutdown
71+
72+
### Async Pattern
73+
All I/O operations are async:
74+
```python
75+
async def search(query, version, language, max_results) -> list[SearchResult]
76+
async def fetch_page(url) -> Optional[PageContent]
77+
```
78+
79+
### Key Data Classes
80+
```python
81+
@dataclass
82+
class SearchResult:
83+
url, title, section, vendor, language, version, content_preview, score
84+
85+
@dataclass
86+
class PageContent:
87+
url, title, content, vendor, language, version, section, last_fetched
88+
```
89+
90+
### MCP Tools Exposed
91+
1. `search_frc_docs` - Multi-vendor search with filters
92+
2. `fetch_frc_doc_page` - Full page content retrieval
93+
3. `list_frc_doc_sections` - Browse available documentation
94+
95+
## Coding Conventions
96+
97+
- Use async/await for all I/O operations
98+
- Type hints on all function signatures
99+
- Dataclasses for structured data
100+
- Graceful error handling (don't crash the server)
101+
- Pre-built JSON indexes stored in each plugin's `data/` directory
102+
103+
## Configuration
104+
105+
`config.json` controls:
106+
- Plugin enable/disable
107+
- Supported languages per vendor (Java, Python, C++)
108+
- Supported versions (2024, 2025)
109+
- Cache TTL and size limits
110+
- Default search parameters
111+
112+
## Testing
113+
114+
```bash
115+
# Run all tests
116+
uv run pytest tests/ -v
117+
118+
# Run specific test file
119+
uv run pytest tests/test_plugins.py -v
120+
uv run pytest tests/test_search.py -v
121+
```
122+
123+
## Entry Point
124+
125+
The package exposes `first-agentic-csa` command which runs `wpilib_mcp.server:main()`

0 commit comments

Comments
 (0)