From 9b04fea63d63af9ef3d26b3999b7391e17294249 Mon Sep 17 00:00:00 2001 From: Monte Brown Date: Wed, 3 Dec 2025 20:32:50 -0500 Subject: [PATCH] Added `mix quality_check` and docs for contributing. - new mix task makes ensuring all quality check pass before committing less onerous. - added a 'Contributing' section to the Readme. - added a basic AGENTS.md. --- AGENTS.md | 49 +++++++++++++++++++++ CHANGELOG.md | 27 +++++++++--- README.md | 31 ++++++++++++++ lib/mix/tasks/quality_check.ex | 78 ++++++++++++++++++++++++++++++++++ 4 files changed, 180 insertions(+), 5 deletions(-) create mode 100644 AGENTS.md create mode 100644 lib/mix/tasks/quality_check.ex diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..dbb8ef6 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,49 @@ +# Agent Guidelines for LangChain MCP + +## Build/Lint/Test Commands + +**Primary Commands:** + +- `mix test` - Run all tests +- `mix test --exclude live_call` - Run only unit tests +- `mix test test/specific_test.exs` - Run single test file +- `mix format --check-formatted` - Check code formatting +- `mix test --cover --exclude live_call` - check code coverage +- `mix quality_check` - Run all quality checks (format, credo, dialyzer, tests) +- `mix credo --strict` - Run linting checks +- `mix dialyzer` - Run type checking +- `mix compile --warnings-as-errors` - Compile with strict warnings + +**Integration Tests:** + +```bash +# Terminal 1: Start test server +mix test_server + +# Terminal 2: Run integration tests +mix test --include live_call +``` + +## Code Style Guidelines + +**Formatting:** + +- Line length: 100 characters (`.formatter.exs`) +- Use `mix format` for consistent formatting + +**Testing:** + +- Unit tests use `Mimic` for mocking, tagged `:live_call` for integration tests +- Tests in `test/` directory follow ExUnit patterns +- Integration tests require running test server (`mix test_server`) + +**Architecture:** + +- Core modules: `LangChain.MCP.*` (Adapter, Config, SchemaConverter, ContentMapper) +- Use proper error handling with `{:ok, _}` / `{:error, _}` tuples +- Follow Elixir naming conventions: snake_case functions, PascalCase modules + +**Dependencies:** + +- Uses `:langchain`, `:anubis_mcp`, `:credo`, `:dialyxir` +- Dev/test deps include mocking (`:mimic`) and docs (`:ex_doc`) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d79eb0..f05becf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,28 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- Initial release +- **Status Monitor**: Lightweight solution for monitoring MCP clients in real-time with uptime percentage tracking +- **Langchain.MCP.Client wrapper**: Decouples Anubis from application, removing dependency requirement +- **Automated release process**: CI workflow automation for streamlined publishing + +### Changed + +- **Default test server port**: Changed from 4000 to 5000 to avoid conflicts with Phoenix applications +- **Folder structure reorganization**: Flattened paths (`lib/langchain/mcp` → `langchain_mcp`, `test/langchain/mcp` → `test/langchain_mcp`) +- **Markdown formatting**: Auto-formatted documentation files using CommonMark standards + +### Fixed + +- ToolExecutor issues resolved +- Test flakiness problems fixed with centralized client management (`async: false` and proper cleanup) +- Registry test bleed eliminated through centralized deregistration +- Dialyzer type checking issues resolved +- Credo linting readability/refactoring opportunities addressed + +## [0.1.0] - Initial release + +### Added + - `LangChain.MCP.Adapter` for converting MCP tools to LangChain functions - `LangChain.MCP.SchemaConverter` for JSON Schema to FunctionParam conversion - `LangChain.MCP.ToolExecutor` for executing MCP tools @@ -19,7 +40,3 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Configurable tool caching - Test infrastructure with mcp/time Docker server - Comprehensive documentation and examples - -## [0.1.0] - TBD - -- Initial release diff --git a/README.md b/README.md index e2788bf..a93e987 100644 --- a/README.md +++ b/README.md @@ -287,6 +287,37 @@ Many MCP servers are available via Docker Hub: See [Docker Hub MCP Catalog](https://hub.docker.com/mcp) for more. +## Contributing + +### Quality Checks +Before pushing, ensure code meets quality standards: + +```bash +# Run all checks (same as CI) +mix quality_check + +# Or run individually: +mix format --check-formatted # Code formatting +mix credo --strict # L linting +mix dialyzer # Type checking +mix test --exclude live_call # Unit tests only +``` + +The automated release workflow requires these checks to pass. Use `mix quality_check` locally before committing. + +### Testing + +- **Unit tests**: Standard ExUnit with mocking via `:mimic` +- **Integration tests**: Tagged `:live_call`, require running test server + +```bash +# Start test server (Terminal 1) +mix test_server + +# Run integration tests (Terminal 2) +mix test --include live_call +``` + ## Architecture ``` diff --git a/lib/mix/tasks/quality_check.ex b/lib/mix/tasks/quality_check.ex new file mode 100644 index 0000000..36ed051 --- /dev/null +++ b/lib/mix/tasks/quality_check.ex @@ -0,0 +1,78 @@ +defmodule Mix.Tasks.QualityCheck do + @moduledoc """ + Runs all quality checks: format, linting, type checking, and tests. + + ## Usage + + mix quality_check + + This runs the same checks as CI: + - Code formatting validation + - Credo linting (strict mode) + - Dialyzer type checking + - Unit tests (excludes live_call integration tests) + + Use before committing to ensure code meets quality standards. + """ + + @shortdoc "Run all quality checks" + + use Mix.Task + + @impl Mix.Task + def run(_args) do + IO.puts("🔍 Running quality checks...\n") + + check_formatting() + check_linting() + check_types() + run_tests() + + IO.puts("\n🎉 All quality checks passed!") + end + + defp check_formatting do + IO.puts("📋 Checking formatting...") + + if Mix.shell().cmd("mix format --check-formatted") != 0 do + IO.puts("�️ Formatting issues found - run 'mix format' to fix") + System.halt(1) + else + IO.puts("✅ Formatting OK") + end + end + + defp check_linting do + IO.puts("\n🔋 Running Credo linting...") + + if Mix.shell().cmd("mix credo --strict") != 0 do + IO.puts("�️ Linting issues found - run 'mix credo' to see details") + System.halt(1) + else + IO.puts("✅ Code quality OK") + end + end + + defp check_types do + IO.puts("\n🔋 Running Dialyzer type checking...") + + if Mix.shell().cmd("mix dialyzer") != 0 do + IO.puts("�️ Type issues found - run 'mix dialyzer' to see details") + System.halt(1) + else + IO.puts("✅ Type checking OK") + end + end + + defp run_tests do + IO.puts("\n🧪 Running unit tests...") + {_, exit_code} = System.cmd("mix", ["test", "--exclude", "live_call"]) + + if exit_code != 0 do + IO.puts("�️ Test failures - check output above") + System.halt(1) + else + IO.puts("✅ All tests pass") + end + end +end