- Move Identity/, Workday/, Intune/ to archive/ (superseded by nexus-mcp shards) - Move 'Local Setup.md' to archive/ (superseded by nexus-mcp/Local-Setup.md) - Add archive/README.md explaining migration and preserved content - Clean repository structure: only nexus-mcp, documentation, and .github remain active All legacy functionality migrated to nexus-mcp sharded architecture. Archived folders preserved for reference and historical context. Refs: SESSION_SNAPSHOT_2026-04-13.md
4.7 KiB
4.7 KiB
Identity MCP implementation kickoff (Phase 1)
Purpose
This document starts implementation of an Identity MCP server with a read-only baseline.
What is implemented
- Python MCP server scaffold using FastMCP
- Read-only tool exposed:
get_user - Read-only tool exposed:
get_user_groups - Read-only tool exposed:
get_group_members - Read-only tool exposed:
find_stale_users - Read-only tool exposed:
get_computer - In-memory backend for local contract testing
- Active Directory backend using PowerShell subprocess wrappers
- Environment-based backend selection (memory vs AD)
- STDERR-only logging for STDIO transport safety
- Basic audit log entries for tool calls
- Unit tests and integration smoke tests
Files
identity_mcp_server.py: FastMCP server, tool definitions, logging, backend selection, and run entrypointidentity_backend.py: backend interface and in-memory implementationad_adapter.py: Active Directory backend using PowerShell Get-AD* cmdletstests/test_ad_adapter.py: unit tests for AD adapter output parsing and error handlingtests/test_integration.py: integration smoke tests against non-production ADpyproject.toml: project metadata, dependency pin for MCP SDK, and CLI entrypoint.gitignore: excludes Python bytecode, test cache, and local virtual environment artifacts
How to run
Using in-memory backend (default, safe mode)
uv run identity_mcp_server.py
Using Active Directory backend
Set environment variables before running:
# Test environment with explicit credentials
export IDENTITY_BACKEND=ad
export AD_USERNAME=your_test_username
export AD_PASSWORD=your_test_password
uv run identity_mcp_server.py
# Production environment with service account context
export IDENTITY_BACKEND=ad
# Service account runs process, no explicit credentials needed
uv run identity_mcp_server.py
Running tests
# Install test dependencies
uv pip install -e ".[test]"
# Run unit tests only (no AD connection required)
pytest tests/test_ad_adapter.py -v
# Run integration smoke tests (requires AD credentials)
export AD_TEST_USERNAME=your_test_username
export AD_TEST_PASSWORD=your_test_password
export AD_TEST_USER=known_test_user
export AD_TEST_GROUP=known_test_group
export AD_TEST_COMPUTER=known_test_computer
pytest tests/test_integration.py -v
# Run all tests
pytest tests/ -v
Active Directory adapter details
Query mapping
get_user: UsesGet-ADUserwith samAccountName filter, retrieves Enabled, DistinguishedName, Description, lastLogonTimestampget_user_groups: UsesGet-ADUserwith MemberOf property, resolves group namesget_group_members: UsesGet-ADGroup+Get-ADGroupMember, filters user objects onlyfind_stale_users: UsesGet-ADUserwith lastLogonTimestamp cutoff (FileTime comparison)get_computer: UsesGet-ADComputer, returns OU and null assigned_username (Phase 1)
Authentication model
- Test environments: explicit username/password via environment variables
- Production: process runs as dedicated service account, no credentials in code
- Service account requires Read Directory Data permission only (no write permissions)
Error handling
All backend failures (timeout, auth denied, permission denied) return:
Nonefor get_user and get_computer (tool wrapper converts to "User not found" or "Computer not found")- Empty list
[]for get_user_groups, get_group_members, find_stale_users
Timeouts
Default: 30 seconds per query. Override with AD_TIMEOUT environment variable.
Known gaps (deferred to later phases)
- Ticket-ID enforcement for write actions (Phase 3)
- PII redaction in audit logs (toggle ready, not enabled by default)
- Entra ID/Azure AD integration (separate adapter)
- Production service account provisioning (infrastructure task)
- Host/client configuration details depend on your selected MCP client
Verification checklist
Before deploying to production:
- Unit tests pass:
pytest tests/test_ad_adapter.py -v - Integration smoke tests pass against non-production AD:
pytest tests/test_integration.py -v - Service account provisioned with Read Directory Data only
- MCP tool responses match expected contract shapes
- Error messages are friendly strings (not exceptions or technical errors)
- Stale-user logic confirmed using lastLogonTimestamp
- Computer assigned_username returns null in Phase 1
- Backend selection tested: memory mode and AD mode both run successfully
Next implementation slice
- Add structured PII redaction toggle for audit logs.
- Add phase gate config that blocks write tools entirely until explicitly enabled (Phase 3 prep).
- Implement Entra ID/Azure AD adapter (separate backend).
- Add canary/rollback mechanism for backend switching.