feat(mcp): add MCP server (reqstool mcp) for AI agent integration#347
Merged
feat(mcp): add MCP server (reqstool mcp) for AI agent integration#347
Conversation
…346) - Add `reqstool mcp local -p PATH` subcommand that starts a FastMCP stdio server exposing 9 tools: list_requirements, get_requirement, list_svcs, get_svc, list_mvrs, get_mvr, get_status, get_requirement_status, list_annotations - Refactor: extract ProjectSession base class (src/reqstool/common/project_session.py) that accepts any LocationInterface and keeps the SQLite DB open for the server lifetime; ProjectState (LSP) now extends it - Refactor: move shared feature functions from lsp/features/ to common/queries/ with RequirementsRepository signatures so both LSP and MCP reuse the same query logic; lsp/features/ wrappers delegate to common/queries/ - urn_source_paths (URN → file path mappings) moved to ProjectSession so AI agents can see which file each requirement is defined in via source_paths - Add mcp[cli]>=1.0 dependency - Add unit tests for ProjectSession, common/queries/details, common/queries/list; update lsp/test_details.py and test_project_state.py for refactored signatures - Add MCP integration tests (tests/integration/reqstool/mcp/) covering all 9 tools against the reqstool-regression-python fixture Signed-off-by: Jimisola Laursen <jimisola@jimisola.com>
Python 3.13 supports all annotation syntax natively (`X | Y`, `dict[str, str]`, etc.). Removed the import from all 48 files and fixed the two forward-reference issues it was masking: - `lifecycle.py`: `LifecycleData.from_dict` return type changed to `Self` - `document_symbols.py`: moved `_YamlItem` class before its first use Signed-off-by: Jimisola Laursen <jimisola@jimisola.com>
Signed-off-by: Jimisola Laursen <jimisola@jimisola.com>
- Replace assert with explicit RuntimeError guard (assert stripped with -O) - Switch mcp[cli]>=1.0 to mcp>=1.0 (cli extra not needed for server use) - Add comment explaining meets_requirements skipped-test semantics Signed-off-by: Jimisola Laursen <jimisola@jimisola.com>
88102b5 to
5bfd399
Compare
datamodel-codegen 0.54.1 still emits this import regardless of --target-python-version. Generated files must match codegen output exactly; the CI codegen-check job was failing as a result. Signed-off-by: Jimisola Laursen <jimisola@jimisola.com>
pytest-asyncio teardown always runs in a different asyncio task than setup, violating anyio's cancel scope invariant. Fix: run the entire stdio_client + ClientSession lifecycle inside a single dedicated task (_lifecycle), signalling shutdown via an asyncio.Event. Setup and teardown now share the same task, so the cancel scope is always entered and exited by the same owner. Also changes fixture scope from module to session (one server instance for the whole test session) and loop_scope accordingly. Signed-off-by: Jimisola Laursen <jimisola@jimisola.com>
Member
Author
|
Tested on a project at work and seems to work fine. MCP server is based on the LSP server where common queries were refactored out. |
- Split get_list into get_requirements_list / get_svcs_list / get_mvrs_list so each list_* tool only fetches the one collection it needs - Add get_requirement_status() to common/queries/details.py — direct repo query avoiding the full get_requirement_details() round-trip - Use project.repo (public property from ProjectSession) instead of project._repo in lsp/features/details.py and lsp/features/list.py - Add unit tests for the three new list functions and get_requirement_status Signed-off-by: Jimisola Laursen <jimisola@jimisola.com>
Member
Author
|
This has been tested with a project that uses reqstool. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #346.
reqstool mcp local -p PATH— new subcommand starting a FastMCP stdio server with 9 tools for AI agent integrationProjectSessionbase class (common/project_session.py) — accepts anyLocationInterface, keeps SQLite DB open for server lifetime;ProjectState(LSP) extends itcommon/queries/— shared feature functions (get_requirement_details,get_svc_details,get_mvr_details,get_requirements_list,get_svcs_list,get_mvrs_list,get_requirement_status) moved out oflsp/features/withRequirementsRepositorysignatures; LSP wrappers delegate to themurn_source_pathspromoted toProjectSessionso AI agents see file paths insource_pathson every get_* responsemcp>=1.0added as dependencyMCP tools (9)
list_requirementsget_requirementlist_svcsget_svclist_mvrsget_mvrget_statusstatus --format json)get_requirement_statuslist_annotations@Requirementsimpl annotations: fqn, element_kindUsage (
.mcp.json){ "mcpServers": { "reqstool": { "command": "reqstool", "args": ["mcp", "local", "-p", "."] } } }Test plan
hatch run dev:pytest tests/unit/ -q— 557 passedhatch run dev:pytest tests/integration/reqstool/lsp/ -m integration— 13 passed (LSP regression)hatch run dev:pytest tests/integration/reqstool/mcp/ -m integration— 13 passed, 0 errorshatch run dev:black ... --check— no changes neededhatch run dev:flake8 ...— cleanhatch run dev:codegen-check— clean