Skip to content

feat(mcp): add MCP server (reqstool mcp) for AI agent integration#347

Merged
jimisola merged 7 commits intomainfrom
feat/mcp-server
Apr 19, 2026
Merged

feat(mcp): add MCP server (reqstool mcp) for AI agent integration#347
jimisola merged 7 commits intomainfrom
feat/mcp-server

Conversation

@jimisola
Copy link
Copy Markdown
Member

@jimisola jimisola commented Apr 18, 2026

Summary

Closes #346.

  • reqstool mcp local -p PATH — new subcommand starting a FastMCP stdio server with 9 tools for AI agent integration
  • ProjectSession base class (common/project_session.py) — accepts any LocationInterface, keeps SQLite DB open for server lifetime; ProjectState (LSP) extends it
  • common/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 of lsp/features/ with RequirementsRepository signatures; LSP wrappers delegate to them
  • urn_source_paths promoted to ProjectSession so AI agents see file paths in source_paths on every get_* response
  • mcp>=1.0 added as dependency

MCP tools (9)

Tool Description
list_requirements All reqs: id, title, lifecycle_state
get_requirement Full req detail incl. SVCs, implementations, source file
list_svcs All SVCs: id, title, lifecycle_state, verification
get_svc Full SVC detail incl. test results, MVRs, source file
list_mvrs All MVRs: id, passed
get_mvr Full MVR detail incl. SVC links, source file
get_status Overall traceability status (maps to status --format json)
get_requirement_status Quick status for one req: implemented? passing?
list_annotations All @Requirements impl annotations: fqn, element_kind

Usage (.mcp.json)

{
  "mcpServers": {
    "reqstool": {
      "command": "reqstool",
      "args": ["mcp", "local", "-p", "."]
    }
  }
}

Test plan

  • hatch run dev:pytest tests/unit/ -q — 557 passed
  • hatch 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 errors
  • hatch run dev:black ... --check — no changes needed
  • hatch run dev:flake8 ... — clean
  • hatch run dev:codegen-check — clean

…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>
@jimisola jimisola self-assigned this Apr 18, 2026
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>
@jimisola jimisola requested a review from Jonas-Werne April 18, 2026 13:57
@jimisola
Copy link
Copy Markdown
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>
@jimisola
Copy link
Copy Markdown
Member Author

This has been tested with a project that uses reqstool.

@jimisola jimisola merged commit d97283b into main Apr 19, 2026
7 checks passed
@jimisola jimisola deleted the feat/mcp-server branch April 19, 2026 08:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: add MCP server (reqstool mcp) for AI agent integration

1 participant