Skip to main content

Plugin-based FRC documentation agent as an MCP server for WPILib and vendor libraries

Project description

FIRST Agentic CSA

A plugin-based FRC documentation agent implemented as a Model Context Protocol (MCP) server. Search across WPILib and vendor documentation (REV, CTRE, Redux, PhotonVision) using natural language queries. Built for FIRST Robotics Competition teams and CSAs (Control System Advisors).

Features

  • Unified Search: Query WPILib + vendor docs with a single tool
  • Plugin Architecture: Extensible system for adding new documentation sources
  • BM25 Ranking: High-quality text search without embedding costs
  • Multi-Vendor Support: WPILib, REV Robotics, CTRE Phoenix, Redux Robotics, PhotonVision
  • Language Filtering: Filter results by Java, Python, or C++
  • Version Support: Search specific documentation versions (2024, 2025, etc.)

Installation

Quick Install (PyPI)

# Using uvx (recommended)
uvx first-agentic-csa

# Or with pip
pip install first-agentic-csa

From Source

If you want to modify or contribute to the project:

  1. Install uv (fast Python package manager):

    Windows (PowerShell):

    powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
    

    macOS/Linux:

    curl -LsSf https://astral.sh/uv/install.sh | sh
    
  2. Clone and install:

    git clone https://github.com/YOUR_USERNAME/first-agentic-csa.git
    cd first-agentic-csa
    uv sync
    

Quick Start

Running the Server

# With uv
uv run first-agentic-csa

# Or directly
python -m wpilib_mcp.server

Configure in Claude Desktop / Cursor

Add to your MCP configuration (claude_desktop_config.json or Cursor settings):

{
  "mcpServers": {
    "frc-docs": {
      "command": "uvx",
      "args": ["first-agentic-csa"]
    }
  }
}

If running from source:

{
  "mcpServers": {
    "frc-docs": {
      "command": "uv",
      "args": ["--directory", "/path/to/first-agentic-csa", "run", "first-agentic-csa"]
    }
  }
}

Configure in Other MCP Clients

The server uses stdio transport and is compatible with any MCP client.

Available Tools

search_frc_docs

Search FRC documentation across WPILib and vendor libraries.

query: "SparkMax configure"
vendors: ["all"] | ["wpilib", "rev", "ctre", "redux"]
version: "2025"
language: "Java" | "Python" | "C++"
max_results: 1-25

fetch_frc_doc_page

Fetch the full content of a documentation page by URL.

url: "https://docs.wpilib.org/en/stable/docs/software/commandbased/commands.html"

list_frc_doc_sections

List available documentation sections from vendors.

vendors: ["all"] | ["wpilib", "rev"]
version: "2025"
language: "Java"

Configuration

Edit config.json to customize plugin settings:

{
  "plugins": {
    "wpilib": {
      "enabled": true,
      "versions": ["2025"],
      "languages": ["Java", "Python", "C++"]
    },
    "rev": {
      "enabled": true,
      "languages": ["Java", "C++"]
    },
    "ctre": {
      "enabled": false
    }
  },
  "cache": {
    "ttl_seconds": 3600
  },
  "search": {
    "default_max_results": 10,
    "default_language": "Java"
  }
}

Supported Plugins

Plugin Vendor Documentation
wpilib WPILib docs.wpilib.org
rev REV Robotics docs.revrobotics.com
ctre CTRE Phoenix v6.docs.ctr-electronics.com
redux Redux Robotics docs.reduxrobotics.com
photonvision PhotonVision docs.photonvision.org

Building Documentation Indexes

Each plugin has its own index builder that vendors can maintain independently.

Using the convenience wrapper:

# Build all plugin indexes
python scripts/build_index.py all

# Build specific vendor
python scripts/build_index.py wpilib --version 2025
python scripts/build_index.py rev
python scripts/build_index.py ctre

Running plugin builders directly:

# Each plugin has its own build_index.py with vendor-specific options
python -m wpilib_mcp.plugins.wpilib.build_index --version stable --verbose
python -m wpilib_mcp.plugins.rev.build_index --verbose
python -m wpilib_mcp.plugins.ctre.build_index --version stable
python -m wpilib_mcp.plugins.redux.build_index

Plugin Development

Create a new plugin by following this structure:

plugins/
└── myplugin/
    ├── __init__.py
    ├── plugin.py        # Must export `Plugin` class
    ├── build_index.py   # Index builder script (vendor-maintained)
    └── data/
        └── index.json

Your Plugin class must implement PluginBase, and you should provide a build_index.py script:

Plugin Implementation

Your Plugin class must implement PluginBase:

from wpilib_mcp.plugins.base import PluginBase, PluginConfig, SearchResult, PageContent, DocSection

class Plugin(PluginBase):
    @property
    def name(self) -> str:
        return "myplugin"
    
    @property
    def display_name(self) -> str:
        return "My Plugin"
    
    @property
    def description(self) -> str:
        return "Description of my plugin"
    
    @property
    def supported_versions(self) -> list[str]:
        return ["2025"]
    
    @property
    def supported_languages(self) -> list[str]:
        return ["Java", "Python"]
    
    @property
    def base_urls(self) -> list[str]:
        return ["https://docs.example.com"]
    
    async def initialize(self, config: PluginConfig) -> None:
        # Load index, build search corpus
        pass
    
    async def search(self, query, version=None, language=None, max_results=10) -> list[SearchResult]:
        # Return search results
        pass
    
    async def fetch_page(self, url) -> PageContent:
        # Fetch and clean page content
        pass
    
    async def list_sections(self, version=None, language=None) -> list[DocSection]:
        # Return documentation sections
        pass

Index Builder

Create a build_index.py that extends BaseIndexBuilder:

from wpilib_mcp.utils.indexer import BaseIndexBuilder

class MyPluginIndexBuilder(BaseIndexBuilder):
    def __init__(self):
        super().__init__(
            vendor="myplugin",
            base_url="https://docs.example.com",
            max_pages=200,
        )
    
    @property
    def start_urls(self) -> list[str]:
        return ["https://docs.example.com/getting-started"]
    
    def should_crawl(self, url: str) -> bool:
        return "docs.example.com" in url
    
    def extract_section(self, soup, url) -> str:
        # Return section name based on URL/content
        return "General"
    
    def extract_language(self, soup, url) -> str:
        return "All"

if __name__ == "__main__":
    import asyncio
    asyncio.run(MyPluginIndexBuilder().build_and_save("latest", Path("data/index.json")))

Index File Format

Each plugin uses a JSON index with this structure:

{
  "vendor": "myplugin",
  "version": "2025",
  "built_at": "2025-01-15T00:00:00Z",
  "pages": [
    {
      "url": "https://docs.example.com/page",
      "title": "Page Title",
      "section": "Section Name",
      "language": "Java",
      "content": "Full searchable content...",
      "content_preview": "First 300 chars for display..."
    }
  ]
}

Development

Running Tests

uv run pytest tests/ -v

Project Structure

wpilib-mcp/
├── pyproject.toml          # Project configuration
├── config.json             # User configuration
├── src/wpilib_mcp/
│   ├── server.py           # MCP server entry point
│   ├── plugin_loader.py    # Plugin discovery/loading
│   ├── tool_router.py      # Routes tools to plugins
│   ├── utils/
│   │   ├── fetch.py        # HTTP with caching
│   │   ├── html.py         # HTML cleaning
│   │   └── search.py       # BM25 search
│   └── plugins/
│       ├── base.py         # Plugin base class
│       ├── wpilib/         # WPILib plugin
│       ├── rev/            # REV plugin
│       ├── ctre/           # CTRE plugin
│       └── redux/          # Redux plugin
├── scripts/
│   └── build_index.py      # Index builder script
└── tests/
    ├── test_search.py
    └── test_plugins.py

Example Queries

Finding Command-Based Programming docs:

search_frc_docs(query="command based programming subsystems", vendors=["wpilib"])

Comparing motor controllers:

search_frc_docs(query="SparkMax configuration", vendors=["rev"])
search_frc_docs(query="TalonFX configuration", vendors=["ctre"])

Looking up specific hardware:

search_frc_docs(query="CANcoder absolute position swerve", vendors=["ctre"])
search_frc_docs(query="through bore encoder", vendors=["rev"])

Cross-vendor search:

search_frc_docs(query="brushless motor closed loop velocity control", vendors=["all"])

MCP Registry & VS Code Marketplace

This MCP server is available in the official MCP Registry and can be discovered through VS Code's MCP integration.

Finding in VS Code

  1. Open VS Code Extensions view
  2. Search for "MCP" or "WPILib"
  3. Browse available MCP servers
  4. Install and configure through VS Code's MCP settings

Registry Listing

For publishing and registry management, see PUBLISHING.md.

License

BSD-3-Clause License - see LICENSE file for details.

Contributing

Contributions welcome! Please:

  1. Fork the repository
  2. Add tests for new functionality
  3. Submit a pull request

For new vendor plugins, please include:

  • Complete plugin implementation
  • Pre-built index file
  • Documentation updates

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

first_agentic_csa-0.3.7.tar.gz (743.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

first_agentic_csa-0.3.7-py3-none-any.whl (692.3 kB view details)

Uploaded Python 3

File details

Details for the file first_agentic_csa-0.3.7.tar.gz.

File metadata

  • Download URL: first_agentic_csa-0.3.7.tar.gz
  • Upload date:
  • Size: 743.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.9.16 {"installer":{"name":"uv","version":"0.9.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for first_agentic_csa-0.3.7.tar.gz
Algorithm Hash digest
SHA256 944c1120fa37e35466ea344d14e06cf9312eb0d246babb917b5e485aa8ed9e2e
MD5 e5a931cc211de1f9d5302bf99016ca6f
BLAKE2b-256 4f617db0e70515371b19650ca5c2bde8c7d73051fbcf1ee32c50e2b32a556a25

See more details on using hashes here.

File details

Details for the file first_agentic_csa-0.3.7-py3-none-any.whl.

File metadata

  • Download URL: first_agentic_csa-0.3.7-py3-none-any.whl
  • Upload date:
  • Size: 692.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.9.16 {"installer":{"name":"uv","version":"0.9.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for first_agentic_csa-0.3.7-py3-none-any.whl
Algorithm Hash digest
SHA256 bc01e08767857b4b4398c65d45e2f440b54a270bc386b8b39ff6c1ded8a3019f
MD5 7461d90783b91bebf2cfbc410b24887a
BLAKE2b-256 a46f3eced4c9e318c20055b3c18c8c9f77686d2f3e38a39184f816fa46d3bf05

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page