# Story 4.2: Implement Secure `fabric_get_configuration` MCP Tool with Targeted Redaction

**Epic:** 4 (Fabric Environment & Configuration Insights)

**Status:** Done

## Story

As an MCP Client Developer, I want to use the `fabric_get_configuration` tool to retrieve the current operational configuration settings of the connected Fabric instance, **with assurances that sensitive values like API keys are redacted**, so that I can display relevant non-sensitive settings or understand the Fabric environment's setup securely.

## Acceptance Criteria (ACs)

1. Tool implemented in `src/fabric_mcp/core.py`. Registered and advertised via `list_tools()` (no params, returns map/object) per `design.md`.
2. Uses `FabricApiClient` for GET to Fabric API `/config` endpoint.
3. Parses JSON response (key-value map) from Fabric API. **Implements targeted redaction:** uses predefined list of sensitive key patterns (e.g., `*_API_KEY`, `*_TOKEN`). For matching keys with non-empty actual values, replaces value with `"[REDACTED_BY_MCP_SERVER]"`. Non-sensitive config values and empty string values are passed through.
4. Returns MCP success response with processed (redacted where needed) JSON object.
5. Returns structured MCP error for Fabric API errors or connection failures.
6. Documentation notes redaction behavior and meaning of empty strings vs. redacted placeholders.
7. Unit tests: mock `FabricApiClient`; test redaction logic (sensitive keys with values are redacted, sensitive keys with empty values passed as empty, non-sensitive keys passed through); test API errors.
8. Integration tests: (vs. live local `fabric --serve` with dummy sensitive env vars set for Fabric) verify MCP response shows keys with `"[REDACTED_BY_MCP_SERVER]"` for sensitive values, and correct pass-through for non-sensitive/empty values.

## Tasks / Subtasks

- [x] Task 1: Update existing `fabric_get_configuration` method implementation (AC: 1, 2, 3, 4, 5)
  - [x] Subtask 1.1: Remove placeholder implementation in `src/fabric_mcp/core.py:fabric_get_configuration()` method
  - [x] Subtask 1.2: Replace with real implementation using `self._make_fabric_api_request("/config", operation="retrieving configuration")`
  - [x] Subtask 1.3: Implement redaction logic function `_redact_sensitive_config_values(config_data: dict[str, Any]) -> dict[str, Any]`
  - [x] Subtask 1.4: Define sensitive key patterns list: `SENSITIVE_CONFIG_PATTERNS = ["*_API_KEY", "*_TOKEN", "*_SECRET", "*_PASSWORD"]`
  - [x] Subtask 1.5: Apply redaction to config response before returning
  - [x] Subtask 1.6: Ensure method returns `dict[Any, Any]` as per existing signature
  - [x] Subtask 1.7: Validate response data type and structure with appropriate error handling

- [x] Task 2: Add comprehensive unit tests for redaction logic (AC: 7)
  - [x] Subtask 2.1: Create `test_fabric_get_configuration` test method in `tests/unit/test_core.py`
  - [x] Subtask 2.2: Test successful API call with mixed sensitive/non-sensitive config
  - [x] Subtask 2.3: Test redaction of sensitive keys with non-empty values
  - [x] Subtask 2.4: Test pass-through of sensitive keys with empty string values
  - [x] Subtask 2.5: Test pass-through of non-sensitive keys regardless of value
  - [x] Subtask 2.6: Test API connection errors using mocked `FabricApiClient`
  - [x] Subtask 2.7: Test HTTP status errors (4xx, 5xx responses)
  - [x] Subtask 2.8: Test invalid JSON response handling

- [x] Task 3: Add integration tests with live Fabric instance (AC: 8)
  - [x] Subtask 3.1: Create integration test in `tests/integration/test_transport_integration.py`
  - [x] Subtask 3.2: Document test setup requirements for setting dummy env vars in Fabric
  - [x] Subtask 3.3: Verify redacted values appear as `"[REDACTED_BY_MCP_SERVER]"` in response
  - [x] Subtask 3.4: Verify non-sensitive and empty values pass through correctly

- [x] Task 4: Update documentation with redaction behavior notes (AC: 6)
  - [x] Subtask 4.1: Add docstring to `fabric_get_configuration` method explaining redaction behavior
  - [x] Subtask 4.2: Document difference between empty string values vs. redacted placeholders
  - [x] Subtask 4.3: List sensitive key patterns in method documentation

## Dev Technical Guidance

### Previous Story Insights

- Story 4.1 implements `fabric_list_models` using similar pattern with `_make_fabric_api_request()` helper method for consistent error handling
- Existing error handling patterns use McpError with specific error codes (-32603 for internal errors, -32602 for invalid params)
- Response validation includes type checking and casting to ensure type safety

### Data Models

- No specific data models required - configuration returned as `dict[str, Any]` key-value map
- Redaction logic operates on dictionary keys using pattern matching
- [Source: architecture/data-models.md - not explicitly documented, inferred from existing patterns]

### API Specifications

- **Fabric API Endpoint**: GET `/config` returns JSON key-value configuration map
- **Authentication**: Uses `FabricApiClient` with `FABRIC_API_KEY` if provided
- **Response Format**: JSON object with configuration key-value pairs
- **Error Handling**: Standard HTTP status codes, connection timeouts
- [Source: architecture/api-reference.md#fabric-rest-api]

### Component Specifications

- **MCP Tool Integration**: Method signature already exists in `FabricMCP` class
- **Registration**: Tool already registered in `__init__` method's tool list
- **Response Format**: MCP success response with dict payload
- [Source: architecture/component-view.md#mcp-tool-implementations]

### File Locations

- **Core Implementation**: `src/fabric_mcp/core.py` (method already exists as placeholder)
- **Unit Tests**: `tests/unit/test_core.py` (existing file, add new test methods)
- **Integration Tests**: `tests/integration/test_mcp_integration.py` (existing file, add new test)
- [Source: architecture/project-structure.md#key-directory-descriptions]

### Testing Requirements

- **Unit Tests**: Mock `FabricApiClient` using `unittest.mock`, 90% coverage target
- **Integration Tests**: Live `fabric --serve` instance with configured env vars
- **Test Patterns**: Follow AAA pattern (Arrange, Act, Assert), use `pytest.raises` for errors
- **Coverage**: Measured with `pytest-cov`, enforced in CI
- [Source: architecture/overall-testing-strategy.md#unit-tests]

### Technical Constraints

- **Python Version**: >=3.11 with CPython runtime
- **Type Safety**: Strict type checking with Pyright, comprehensive type hints mandatory
- **Error Handling**: Use async/await for HTTP operations, proper exception handling
- **Dependencies**: httpx for HTTP client, use existing `FabricApiClient` abstraction
- [Source: architecture/definitive-tech-stack-selections.md, coding-standards.md#type-safety]

### Security Considerations

- **Redaction Patterns**: Must catch variations like `OPENAI_API_KEY`, `FABRIC_TOKEN`, etc.
- **Pattern Matching**: Use wildcard matching (`*_API_KEY`, `*_TOKEN`, `*_SECRET`, `*_PASSWORD`)
- **Empty Values**: Don't redact empty strings to distinguish from actual redacted values
- **Logging**: Ensure no sensitive values leak into debug logs during development

## Dev Notes

### Testing

Dev Note: Story Requires the following tests:

- [x] Pytest Unit Tests: (nextToFile: false), coverage requirement: 95%
- [x] Pytest Integration Test (Test Location): location: `tests/integration/test_mcp_integration.py` using the mock server (see ./tests/shared/fabric_api/server.py)
- [x] E2E: location: Not required for this story

Manual Test Steps:

- Start local `fabric --serve` with some API keys configured in environment
- Run fabric-mcp server and connect via MCP inspector
- Execute `fabric_get_configuration` tool and verify:
  - Sensitive keys (ending in _API_KEY, _TOKEN, etc.) show `[REDACTED_BY_MCP_SERVER]`
  - Non-sensitive keys show actual values
  - Empty sensitive keys show empty strings, not redaction placeholder

## Dev Agent Record

### Agent Model Used: Claude 4 Sonnet

### Debug Log References

No specific debug logging was required during this story implementation. All development proceeded smoothly following the established patterns from previous stories.

### Completion Notes List

**Key Implementation Details:**

- Successfully implemented targeted redaction using `fnmatch` for case-insensitive pattern matching
- Added comprehensive unit tests covering all redaction scenarios and error conditions
- Enhanced mock Fabric API server with `/config` endpoint to support integration testing
- All 225 tests passing, maintaining 100% test suite success rate

**Technical Decisions:**

- Used `fnmatch.fnmatch()` for pattern matching to support wildcard patterns like `*_API_KEY`
- Implemented case-insensitive matching by converting keys to lowercase before pattern comparison
- Added `with_json_response()` method usage in tests instead of the incorrect `with_successful_response()`
- Enhanced integration test to use mock server instead of real Fabric API for predictable testing

**Deviations from Original Plan:**

- Integration test was placed in `test_transport_integration.py` instead of `test_mcp_integration.py` to follow existing project patterns
- Added `/config` endpoint to mock server (`tests/shared/fabric_api/server.py`) which wasn't originally present
- Removed direct testing of protected `_redact_sensitive_config_values()` method to follow project testing conventions

**Story Impact on Future Work:**

- Mock server now supports configuration endpoint for other stories that might need config testing
- Established redaction pattern that could be reused for other sensitive data scenarios
- Comprehensive test patterns for API error handling can be applied to future MCP tools

### Change Log

| Date | Version | Description | Author |
| :--- | :------ | :---------- | :----- |
| 2025-06-20 | 1.0 | Initial story implementation completed with all ACs satisfied | Claude 3.5 Sonnet |
| 2025-06-20 | 1.1 | Added `/config` endpoint to mock Fabric API server for integration testing | Claude 3.5 Sonnet |
| 2025-06-20 | 1.2 | Fixed integration test to use mock server, achieving 100% test pass rate | Claude 3.5 Sonnet |
| 2025-06-20 | 1.3 | Final cleanup: Fixed all trailing whitespace issues, all 226 tests pass | Claude 3.5 Sonnet |
| 2025-06-20 | 1.4 | Refactoring, cleanup, break up large code files | Kayvan Sylvan |
