Skip to content

Commit 0b6e3a4

Browse files
committed
docs: clarify rust workspace policy and follow-ups
Signed-off-by: lucarlig <luca.carlig@ibm.com>
1 parent ca66b34 commit 0b6e3a4

File tree

13 files changed

+53
-67
lines changed

13 files changed

+53
-67
lines changed

AGENTS.md

Lines changed: 8 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ For domain-specific guidance, see subdirectory AGENTS.md files:
88
- `charts/AGENTS.md` - Helm chart operations
99
- `docs/AGENTS.md` - Documentation authoring
1010
- `mcp-servers/AGENTS.md` - MCP server implementation
11-
- `tools_rust/mcp_runtime/DEVELOPING.md` - Rust MCP runtime development workflows, command matrix, and validation
11+
- `crates/mcp_runtime/DEVELOPING.md` - Rust MCP runtime development workflows, command matrix, and validation
1212

1313
**Note:** The `llms/` directory contains guidance for LLMs *using* ContextForge solution (end-user runtime guidance), not for code agents working on this codebase.
1414

@@ -38,7 +38,7 @@ charts/ # Helm charts (see charts/AGENTS.md)
3838
docs/ # Architecture and usage documentation (see docs/AGENTS.md)
3939
a2a-agents/ # A2A agent implementations (used for testing/examples)
4040
mcp-servers/ # MCP server templates (see mcp-servers/AGENTS.md)
41-
tools_rust/ # Rust utilities and MCP runtime (see tools_rust/mcp_runtime/DEVELOPING.md)
41+
crates/ # Direct Rust crate folders (runtime and wrapper)
4242
llms/ # End-user LLM guidance (not for code agents)
4343
```
4444

@@ -48,9 +48,8 @@ llms/ # End-user LLM guidance (not for code agents)
4848
```bash
4949
cp .env.example .env && make install-dev check-env # Complete setup
5050
make venv # Create virtual environment with uv
51-
make install-dev # Install with dev dependencies (includes build-ui)
51+
make install-dev # Install with dev dependencies
5252
make check-env # Verify .env against .env.example
53-
make build-ui # Rebuild Admin UI JS bundle (requires npm)
5453
```
5554

5655
### Development
@@ -66,11 +65,10 @@ make serve-ssl # HTTPS on :4444 (creates certs if needed)
6665
make autoflake isort black pre-commit
6766

6867
# Before committing, use ty, mypy and pyrefly to check just the new files, then run:
69-
make ruff bandit interrogate pylint verify
68+
make flake8 bandit interrogate pylint verify
7069

71-
# Before committing Rust changes (tools_rust/):
72-
# Run fmt-check, clippy -D warnings, and cargo test for Rust crates
73-
cd tools_rust/mcp_runtime && cargo fmt --check && cargo clippy -- -D warnings && cargo test
70+
# Before committing Rust changes (crates/ or tools_rust/):
71+
make rust-check # Runs fmt-check, clippy -D warnings, and cargo test for all Rust crates
7472
```
7573

7674
## Authentication & RBAC Overview
@@ -137,39 +135,6 @@ ContextForge implements a **two-layer security model**:
137135
- **Multi-tenancy architecture**: `docs/docs/architecture/multitenancy.md`
138136
- **OAuth token delegation**: `docs/docs/architecture/oauth-design.md`
139137

140-
## Observability Transaction Behavior
141-
142-
**Issue #3883 - Separate Session Pattern**
143-
144-
Observability write operations use **independent database sessions** that commit immediately (best-effort pattern). This means:
145-
146-
- Observability data persists even when the main request fails
147-
- Traces may show "in progress" or partial states for failed requests
148-
- **NOT atomic** with main request transaction (intentional trade-off)
149-
- Provides visibility into partial failures at the cost of atomicity
150-
151-
### Implementation Details
152-
153-
**Write methods** (use independent sessions):
154-
- `start_trace()`, `end_trace()`
155-
- `start_span()`, `end_span()`
156-
- `add_event()`, `record_token_usage()`, `record_metric()`, `delete_old_traces()`
157-
158-
**Query methods** (use request-scoped sessions):
159-
- `get_trace()`, `get_traces()`, `get_spans()`, etc.
160-
- These accept a `db: Session` parameter for RBAC/token scoping
161-
162-
**Context managers** (create single independent session for lifecycle):
163-
- `trace_span()`, `trace_tool_invocation()`, `trace_a2a_request()`
164-
165-
**Pattern**: Follows existing SQL instrumentation approach in `instrumentation/sqlalchemy.py:58-87`
166-
167-
**Middleware**: `ObservabilityMiddleware` no longer creates `request.state.db`. Each observability operation creates its own short-lived session.
168-
169-
**Security**: Query operations use request-scoped sessions for RBAC/token scoping. Write operations are not RBAC-protected (observability visibility is platform-wide).
170-
171-
**Connection Pool Sizing**: The separate session pattern creates 4-6 independent database sessions per traced request (trace start/end, span start/end, metrics, events). Default configuration (`DB_POOL_SIZE=200`, `DB_MAX_OVERFLOW=10`) provides 210 total connections, supporting ~35 concurrent traced requests. This is adequate for typical deployments. High-traffic production systems (>50 req/sec sustained) should increase pool size via environment variables: `DB_POOL_SIZE=500`, `DB_MAX_OVERFLOW=100` to support 80+ concurrent requests. Monitor for "QueuePool limit exceeded" errors and adjust pool sizing accordingly. Note: SQLite connections are capped at 50 due to file-based limitations.
172-
173138
## Key Environment Variables
174139

175140
Defaults come from `mcpgateway/config.py`. `.env.example` intentionally overrides a few for local/dev convenience.
@@ -368,6 +333,5 @@ When posting PR reviews, issue comments, or any public-facing text on GitHub, us
368333

369334
- `gh` for GitHub operations
370335
- `make` for build/test automation
371-
- `uv` for virtual environment management and for `uv tool run` linter invocations
372-
- Dev-group tools installed in the venv: `pytest`, `mypy`, `bandit`, `pre-commit`, `prospector`, etc. (see `pyproject.toml` `[dependency-groups]`)
373-
- Formatters and linters (`black`, `isort`, `ruff`, `pylint`, `vulture`, `interrogate`, `radon`, `yamllint`, `tomlcheck`) are pinned in the `Makefile` and invoked on demand via `uv tool run`; always prefer the Makefile targets (`make black`, `make ruff`, `make pylint`, etc.) over calling the underlying tools directly
336+
- `uv` for virtual environment management
337+
- Standard tools: pytest, black, isort, ruff, pylint

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,11 @@ conditions:
6060

6161
**Rollback**: Keep configuration backups. Restore previous `plugins/config.yaml` if issues arise.
6262

63+
### Changed
64+
65+
- Consolidated the repository-owned Rust workspace under `crates/`, kept root-level `cargo build` / `cargo test` / `cargo check` support, and documented that `mcp-servers/rust/` stays outside the shared workspace for now. ([#4087](https://github.com/IBM/mcp-context-forge/pull/4087))
66+
- Added workspace-level Rust policy notes for contributors, tracked `cargo-vet` exemption reduction in [#4173](https://github.com/IBM/mcp-context-forge/issues/4173), and tracked Rust CI workflow factoring in [#4174](https://github.com/IBM/mcp-context-forge/issues/4174).
67+
6368
#### **👥 `MAX_MEMBERS_PER_TEAM` No Longer Baked Into Team Rows** ([#3682](https://github.com/IBM/mcp-context-forge/pull/3682), [#3588](https://github.com/IBM/mcp-context-forge/issues/3588))
6469

6570
**Action Required**: New teams now store `NULL` for `max_members` and resolve the limit at check time from the `MAX_MEMBERS_PER_TEAM` environment variable. Existing teams created before this change still have the old default baked into the DB and will **not** automatically pick up env var changes.

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -658,6 +658,12 @@ make venv install-dev # create .venv + install deps + build Admin UI
658658
make serve # gunicorn on :4444
659659
```
660660

661+
Rust workspace note:
662+
- Workspace-owned Rust crates live under `crates/` and are picked up by the root `Cargo.toml` via `crates/*`.
663+
- Run `cargo build`, `cargo test`, and `cargo check` from the repo root to cover the shared workspace.
664+
- `mcp-servers/rust/` stays outside the shared workspace on purpose and is managed separately.
665+
- `make venv install-dev` creates the root `.venv`, which is also reused by the workspace's PyO3/maturin builds.
666+
661667
<details>
662668
<summary><strong>Alternative: UV or pip</strong></summary>
663669

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# ADR-0041: Top-Level Rust Workspace (Cargo.toml at Repository Root)
22

3-
- *Status:* Partially superseded — `plugins_rust/` was removed when in-tree Rust plugins migrated to standalone PyPI packages (`cpex-*`). The remaining Rust workspace members (`tools_rust/`, etc.) are unaffected.
3+
- *Status:* Accepted
44
- *Date:* 2026-02-26
55
- *Deciders:* Core Engineering Team
66

@@ -13,30 +13,34 @@ The repository is primarily Python-based with some Rust usage (e.g. plugins, too
1313
Adopt **Option 1: workspace at repository root**.
1414

1515
- Add a root `Cargo.toml` defining a Rust workspace.
16-
- Include Rust crates as workspace members at the repository root. At the time of the decision that meant `mcpgateway_rust/`, `tools_rust/`, and `plugins_rust/`. After the plugin extraction, only the remaining in-repo Rust crates (for example `tools_rust/`) still participate in this workspace.
17-
- Keep the existing directory layout: Python in `mcpgateway/`, `plugins/`, etc.; Rust crates remain where they are and are referenced from the root workspace.
16+
- Keep the root workspace member policy simple: workspace-owned crates live under `crates/`, and the root manifest includes them via `crates/*`.
17+
- Keep the existing directory layout: Python stays in `mcpgateway/`, `plugins/`, and related top-level folders; the Rust workspace-owned crates live in `crates/`.
18+
- Keep `mcp-servers/rust/` out of the shared workspace. Those sample/test servers remain separately managed and can move out of the repository later if we give them a plugin-like distribution path.
1819
- PyO3/maturin bindings and CI for Rust builds and tests follow this workspace (see [#3027](https://github.com/IBM/mcp-context-forge/issues/3027) for make targets and acceptance criteria).
1920

2021
## Consequences
2122

2223
### Positive
2324

2425
- Single `cargo build` / `cargo test` / `maturin build` at repo root for all Rust code.
26+
- Clear placement rule for future workspace crates: if it belongs to the shared root workspace, it goes under `crates/`.
2527
- Centralized dependency management and simpler CI.
2628
- Easier cross-crate refactors; natural place to add future Rust components.
2729
- **Maturin** (by default with a top-level workspace) uses the root `.venv` instead of creating venvs at lower levels—one shared Python environment and simpler dev setup.
2830

2931
### Negative
3032

3133
- Rust and Python directories live side-by-side at root; language boundary is less visually isolated than a dedicated `rust/` folder.
34+
- Rust sample/test servers outside `crates/` need their own packaging and release handling until they move to a separate distribution model.
3235

3336
## Alternatives Considered
3437

35-
- **Option 2 (dedicated `mcpgateway_rust/` as workspace root)**: Clearer language boundary but extra `cd`/Make indirection and, at the time, no single root-level workspace for plugins.
38+
- **Option 2 (dedicated `mcpgateway_rust/` as workspace root)**: Clearer language boundary but extra `cd`/Make indirection and no single root-level workspace.
3639
- **Option 3 (hybrid `rust/` folder with gateway_core boundary)**: Deferred; can be revisited if we want a stricter FFI boundary.
3740
- **Option 4+ (Rust as services / split repos / full rewrite)**: Out of scope for this decision.
3841

3942
## Related
4043

4144
- Issue: [https://github.com/IBM/mcp-context-forge/issues/3027](https://github.com/IBM/mcp-context-forge/issues/3027)
42-
- **Supersedes** (build layout): [ADR-0039](039-adopt-fully-independent-plugin-crates-architecture.md)—plugin crates remained independent per ADR-0039, and while they were still in this repo they also participated in the top-level workspace.
45+
- Follow-up: [#4174](https://github.com/IBM/mcp-context-forge/issues/4174) tracks factoring the large Rust CI workflow into reusable building blocks.
46+
- **Supersedes** (build layout): [ADR-0039](039-adopt-fully-independent-plugin-crates-architecture.md) for the internal workspace-owned Rust layout. Independent Rust packages can still live outside the workspace when they need separate release metadata or lifecycles.

docs/docs/architecture/adr/042-enforce-rust-in-build-process.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,4 +125,4 @@ Making Rust mandatory in the build affects **new and existing contributors** who
125125
- [Open PRs with `rust` label](https://github.com/IBM/mcp-context-forge/pulls?q=is%3Aopen+is%3Apr+label%3Arust) — examples of main Rust components being implemented
126126
- ADR-0020: Multi-Format Packaging Strategy (wheels, containers, Helm)
127127
- ADR-0038: Experimental Rust Transport Backend (Streamable HTTP) — first main Rust component in the gateway
128-
- Plugin crates (e.g. `plugins_rust/`) are out of scope for this ADR; they have their own packaging and optional/required policy.
128+
- Plugin crates and Rust MCP servers with their own packaging lifecycle are out of scope for this ADR; they keep their own optional/required policy.

docs/docs/architecture/adr/043-rust-mcp-runtime-sidecar-mode-model.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,5 +194,5 @@ the documented operator model is the high-level mode switch above.
194194

195195
- [Rust MCP Runtime Architecture](../rust-mcp-runtime.md)
196196
- [Performance Architecture](../performance-architecture.md)
197-
- `tools_rust/mcp_runtime/TESTING-DESIGN.md` in the repository
198-
- `tools_rust/mcp_runtime/README.md` in the repository
197+
- `crates/mcp_runtime/TESTING-DESIGN.md` in the repository
198+
- `crates/mcp_runtime/README.md` in the repository

docs/docs/architecture/explorer.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4821,10 +4821,11 @@ <h3>Testing Matrix</h3>
48214821
{ name:"Docker Security Scan", file:"docker-scan.yml", desc:"Build locally, generate SBOM with Syft, upload artifact.", triggers:["push","PR"] },
48224822
{ name:"Helm Chart Publish", file:"helm-publish.yml", desc:"Lint mcp-stack chart, publish to OCI registry on release.", triggers:["push","PR","release"] },
48234823
{ name:"Python Package Build", file:"python-package.yml", desc:"Build sdist and wheel (make dist) on code changes.", triggers:["push","PR"] },
4824+
{ name:"Pytest With Rust", file:"pytest-rust.yml", desc:"Full pytest suite with Rust build/install enabled for Rust-owned changes.", triggers:["push","PR"] },
48244825
{ name:"JavaScript Tests (Vitest)", file:"vitest.yml", desc:"Vitest unit tests for browser JavaScript (jsdom environment).", triggers:["push","PR"] },
48254826
{ name:"Web Lint", file:"lint-web.yml", desc:"ESLint, HTMLHint, Stylelint in separate matrix jobs.", triggers:["push","PR"] },
48264827
{ name:"Playwright CI Smoke", file:"playwright.yml", desc:"UI automation smoke tests against live gateway.", triggers:["push","PR","manual"] },
4827-
{ name:"Rust Tools CI/CD", file:"rust-tools.yml", desc:"Cargo test and clippy for tools_rust/ and mcp-servers/rust/.", triggers:["push"] },
4828+
{ name:"Rust CI", file:"rust.yml", desc:"Unified Rust workspace CI for build, lint, tests, wheels, audit, coverage, and docs.", triggers:["push","PR","manual"] },
48284829
{ name:"Alembic Upgrade Validation", file:"alembic-upgrade-validation.yml", desc:"Validate DB migration paths (upgrade testing).", triggers:["PR","push","manual"] },
48294830
{ name:"License Check", file:"license-check.yml", desc:"Scan for license compliance on dependency changes.", triggers:["push","PR"] },
48304831
{ name:"Full Linting", file:"linting-full.yml", desc:"Comprehensive linting pass on main branch.", triggers:["push","manual"] },

docs/docs/architecture/rust-mcp-runtime.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ make test-mcp-session-isolation
116116
```
117117

118118
See the detailed threat model and test matrix in
119-
`tools_rust/mcp_runtime/TESTING-DESIGN.md` in the repository.
119+
`crates/mcp_runtime/TESTING-DESIGN.md` in the repository.
120120

121121
## Verification
122122

@@ -244,7 +244,7 @@ make testing-rebuild-rust-full
244244
make test-mcp-cli
245245
make test-mcp-rbac
246246
make test-mcp-session-isolation
247-
cargo test --release --manifest-path tools_rust/mcp_runtime/Cargo.toml
247+
cargo test --release --manifest-path crates/mcp_runtime/Cargo.toml
248248
```
249249

250250
Recommended benchmark wrappers:
@@ -257,4 +257,4 @@ make benchmark-mcp-tools-300
257257
```
258258

259259
For Rust-local profiling and crate-level lint/test helpers, see
260-
`tools_rust/mcp_runtime/README.md` in the repository.
260+
`crates/mcp_runtime/README.md` in the repository.

docs/docs/best-practices/mcp-best-practices.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ Make targets are grouped by functionality. Use `make help` to see them all in yo
3030
| Target | Description |
3131
|----------------------|-------------|
3232
| `make serve` | Run the MCP server locally (e.g., `mcp-time-server`). |
33-
| `make test` | Run all unit and integration tests with `pytest`. |
33+
| `make test` | Run all unit and integration tests with `pytest`. Use `pytest -k "<name>" tests/unit/` for targeted runs. |
3434
| `make test-curl` | Run public API integration tests using a `curl` script. |
3535

3636
#### 📚 DOCUMENTATION & SBOM

docs/docs/development/profiling.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -243,15 +243,15 @@ py-spy record -o flamegraph.svg -- python -m mcpgateway
243243
For Rust-local profiling of the MCP runtime crate:
244244

245245
```bash
246-
make -C tools_rust/mcp_runtime setup-profiling
247-
make -C tools_rust/mcp_runtime flamegraph-test
248-
make -C tools_rust/mcp_runtime flamegraph-test-rmcp
246+
make -C crates/mcp_runtime setup-profiling
247+
make -C crates/mcp_runtime flamegraph-test
248+
make -C crates/mcp_runtime flamegraph-test-rmcp
249249
```
250250

251251
These targets generate flamegraphs under:
252252

253253
```text
254-
tools_rust/mcp_runtime/profiles/
254+
crates/mcp_runtime/profiles/
255255
```
256256

257257
Use them to inspect Rust-internal startup and hot-path behavior in the runtime

0 commit comments

Comments
 (0)