# Research Findings: MCP SSO Checklist Server
**Date**: 2025-12-11
**Feature**: 001-mcp-sso-checklist
## Executive Summary
Research completed for all technical dependencies. All unknowns resolved with clear
technology choices aligned with architecture.md decisions.
---
## 1. MCP Python SDK
### Decision
Use `mcp` package version 1.23.3 with FastMCP high-level API and HTTP Streamable transport.
### Rationale
- FastMCP provides clean decorator-based tool registration
- HTTP Streamable is the recommended production transport (per ADR-001)
- Stateless mode with JSON responses recommended for simplicity
- Auto-generates tool schemas from type hints and docstrings
### Key Findings
**Version**: 1.23.3 (latest stable)
**Installation**: `uv add mcp`
**HTTP Streamable Configuration**:
```python
from mcp.server.fastmcp import FastMCP
mcp = FastMCP(
"SSO Checklist Server",
stateless_http=True,
json_response=True # No SSE complexity for simple request-response
)
@mcp.tool()
def get_checklist(name: str) -> str:
"""Get a development checklist by name."""
# Implementation
pass
mcp.run(transport="streamable-http", port=8080)
```
**Tool Registration Pattern**:
- Use `@mcp.tool()` decorator
- Type hints and docstrings auto-generate tool schema
- Return types determine response format
### Alternatives Considered
1. **stdio transport**: Simpler but limited debugging capabilities
2. **SSE transport**: Being deprecated in favor of Streamable HTTP
3. **Low-level MCP API**: More control but unnecessary complexity
### Architecture Alignment
- Aligns with ADR-001 (HTTP Streamable transport)
- Supports architecture.md Component View structure
- Default port 8080 per spec clarification
---
## 2. MSAL Python (Azure Authentication)
### Decision
Use `msal` with `msal-extensions` for OAuth 2.0 Authorization Code flow with PKCE and
secure token persistence.
### Rationale
- Official Microsoft library with automatic PKCE support
- msal-extensions provides cross-platform encrypted token storage
- Handles token refresh automatically
- Well-documented, battle-tested implementation
### Key Findings
**Versions**:
- `msal`: Latest (September 2025)
- `msal-extensions`: Latest (March 2025)
**Installation**: `uv add msal msal-extensions`
**Authentication Flow**:
```python
from msal import PublicClientApplication
from msal_extensions import build_encrypted_persistence, PersistedTokenCache
# Build encrypted token cache
persistence = build_encrypted_persistence("~/.sso-mcp-server/token_cache.bin")
cache = PersistedTokenCache(persistence)
# Create public client app
app = PublicClientApplication(
client_id=os.environ["AZURE_CLIENT_ID"],
authority=f"https://login.microsoftonline.com/{os.environ['AZURE_TENANT_ID']}",
token_cache=cache
)
# Try silent first, then interactive
accounts = app.get_accounts()
if accounts:
result = app.acquire_token_silent(scopes=["User.Read"], account=accounts[0])
if not accounts or "access_token" not in result:
result = app.acquire_token_interactive(scopes=["User.Read"])
```
**Token Persistence**:
- msal-extensions uses platform-specific encryption:
- Windows: DPAPI
- macOS: KeyChain
- Linux: LibSecret
- Automatic file locking for concurrent access
- Graceful fallback to plaintext if encryption unavailable
### Alternatives Considered
1. **authlib**: Generic OAuth library - rejected for less Azure integration
2. **Device Code Flow**: More friction, unfamiliar UX
3. **Client Credentials**: Requires secret management, no user identity
### Architecture Alignment
- Aligns with ADR-002 (OAuth 2.0 with PKCE)
- Aligns with ADR-004 (MSAL for Azure)
- Aligns with ADR-005 (Secure token persistence)
---
## 3. Frontmatter Parsing
### Decision
Use `python-frontmatter` library version 1.1.0 for YAML frontmatter parsing.
### Rationale
- Mature, well-maintained library (MIT license)
- Clean API with dictionary-style access
- Supports YAML, TOML, JSON formats
- Uses safe YAML loading by default
### Key Findings
**Version**: 1.1.0
**Installation**: `uv add python-frontmatter`
**Usage Pattern**:
```python
import frontmatter
def parse_checklist(file_path: str) -> tuple[dict, str]:
"""Parse checklist file, returning metadata and content."""
with open(file_path, encoding='utf-8') as f:
post = frontmatter.load(f)
metadata = {
'name': post.get('name', file_path.stem),
'description': post.get('description', '')
}
return metadata, post.content
```
**Checklist File Format**:
```yaml
---
name: Coding Standards Checklist
description: Quality checklist for code reviews and development
---
# Coding Standards
- [ ] Follow naming conventions
- [ ] Add unit tests
...
```
### Alternatives Considered
1. **Manual YAML parsing**: More code, error-prone
2. **PyYAML directly**: No frontmatter separation
3. **Custom regex**: Fragile, hard to maintain
### Architecture Alignment
- Aligns with ADR-003 (Local file system storage)
- Supports spec FR-018 (YAML frontmatter parsing)
- Supports checklist format from architecture.md §6.1
---
## 4. Additional Dependencies
### HTTP Server (for MCP)
- **Decision**: Use built-in FastMCP server (aiohttp-based)
- **Rationale**: FastMCP handles HTTP server setup automatically
- **Alternative**: FastAPI mount - rejected for added complexity
### Configuration Management
- **Decision**: Use environment variables with python-dotenv fallback
- **Rationale**: Standard practice, 12-factor app compliance
- **Alternative**: Config files - environment vars are simpler
### Logging
- **Decision**: Use Python's built-in logging with structlog for structured output
- **Rationale**: Ground rules require structured logging for troubleshooting
- **Alternative**: loguru - structlog better for JSON output
---
## Dependency Summary
| Package | Version | Purpose |
|---------|---------|---------|
| mcp | ^1.23.3 | MCP protocol implementation |
| msal | ^1.30.0 | Azure OAuth 2.0 authentication |
| msal-extensions | ^1.2.0 | Encrypted token persistence |
| python-frontmatter | ^1.1.0 | YAML frontmatter parsing |
| python-dotenv | ^1.0.0 | Environment variable loading |
| structlog | ^24.0.0 | Structured logging |
---
## Open Questions Resolved
| Question | Resolution |
|----------|------------|
| MCP SDK version? | 1.23.3 with FastMCP |
| HTTP transport pattern? | Streamable HTTP, stateless, JSON response |
| Token storage encryption? | msal-extensions with platform encryption |
| Frontmatter library? | python-frontmatter 1.1.0 |
---
## References
- MCP Python SDK: https://github.com/modelcontextprotocol/python-sdk
- FastMCP GitHub: https://github.com/jlowin/fastmcp
- FastMCP Tutorial: https://www.firecrawl.dev/blog/fastmcp-tutorial-building-mcp-servers-python
- MSAL Python: https://learn.microsoft.com/en-us/entra/msal/python/
- MSAL Token Acquisition: https://learn.microsoft.com/en-us/entra/msal/python/getting-started/acquiring-tokens
- MSAL Token Cache: https://learn.microsoft.com/en-us/entra/msal/python/advanced/msal-python-token-cache-serialization
- msal-extensions: https://github.com/AzureAD/microsoft-authentication-extensions-for-python
- python-frontmatter: https://python-frontmatter.readthedocs.io/
- python-frontmatter PyPI: https://pypi.org/project/python-frontmatter/
---
**Last Updated**: 2025-12-11
**Reviewed**: All findings validated against architecture.md ADRs