Bahn: aisupport, Analyse-O2C-C2S, awesome-bahn-mcp-servers, beam-mcp,
Confluence_Bot, db-planet-mcp-server, O2C-Harness, project-audit,
Projekt-KIQ-HP, teamlandkarte-mcp
Dhive: Jury-Voting
Privat: CV, NoteGraph (NOTE: NoteGraph needs complete redo after consolidation)
Shared: AI-Orchestrator, OrgMyLife, power_skills_and_more
Shared/references: symphony (read-only)
Bahn repos remain available as independent remotes - this monorepo
pulls them in via subtree, the originals are untouched.
8.8 KiB
Change: Add Capacity Matching MCP Server (Stage 1)
Why
DB Systel employees have free work capacities stored in the Open Data Lake, but there's no efficient way for AI assistants to match these capacities with tasks. Tasks are also stored in the database, but finding suitable capacities for them requires manual work. This MCP server will enable AI clients to automatically:
- Browse and search published tasks from the database
- Validate task requirements (comparing DB skills vs description-extracted skills)
- Find the best-suited employees for both database tasks and ad-hoc requirements
- Match capacities based on competences and role, with optional availability (date-range) filtering
What Changes
- Add MCP server implementation with 10-tool workflow (task management, requirement gathering, search, and refinement)
- Add database task management (4 new tools): list tasks, view details, validate requirements, automated search
- Add task database integration: Query published tasks with skills from Beschaffungstool KMP tables
- Add requirement validation: Compare database skills vs LLM-extracted skills from description
- Add common extraction function: DRY principle with
_extract_requirements_from_description() - Add internal helper functions:
extract_requirements_from_task(),extract_roles_from_task() - Add database connection layer for Trino/Presto with single join query
- Requirement extraction and semantic matching are implemented via Azure OpenAI:
- Chat completions for role/requirement extraction
- Embeddings + cosine similarity for semantic similarity scoring
- Errors are deterministic (no heuristic fallbacks)
Historical note (2026-02): The initial Stage-1 proposal assumed only client-side LLM access via MCP sampling and used heuristic fallbacks because sampling was not available in the runtime. The current implementation has been migrated to an Azure OpenAI-only integration (see change
replace-heuristics-with-azure-openai).
- Add session state management for requirement tracking across tool calls
- Add configurable scoring system with categorical results (Top/Good/Partial/Low)
- Add two-tier caching: database cache (12h TTL) and search results cache (60min TTL) with task_id tracking
- Emit deterministic, machine-readable headers in search-related tool outputs so MCP
clients can reliably capture
search_id/filter_id:- first line:
Using SEARCH_ID=<uuid> - plus
SEARCH_ID=<uuid>,FILTER_ID=<uuid>(if applicable),META=<json>
- first line:
- Reject non-UUID
search_idvalues early with a clear message - Track the latest search id internally for debugging/consistency, but do not expose a "last search id" tool (multi-user/session unsafe)
- Add requirement workflow: extract from free text, collect structured, or update requirements
- Add explicit confirmation before search execution
- Remove availability from weighted scoring (availability is displayed and can be used as a filter)
- Update default weights: competence 0.8, role 0.2
- Keep date range as an optional availability filter (when provided)
- Add interactive result exploration with search session management (search_id)
- Add fuzzy filtering for post-search refinement (role and/or competences as list)
- Add filter tracking with filter_id (no search_id proliferation)
- Add pagination for result browsing (20 results per page)
- Add database configuration in
database.toml(Trino) - Add Arc42 architecture documentation with ADRs
Strict two-step confirmation (Review → Ask → Confirm)
When matching.require_confirmation = true (default), the server enforces a
strict, user-driven confirmation sequence before any matching run:
- Requirements are captured/updated into pending state (e.g. via
extract_requirements,collect_structured_requirement_data,update_requirements, or guided capture tools). - The assistant must review pending requirements using
show_pending_requirements()(preferred) or, if requirements were already shown to the user in chat, callrequest_requirements_confirmation()as a marker. - The assistant must ask the user explicitly for Yes/No confirmation.
- Only after user approval, the assistant calls
confirm_requirements(confirm=true). If the user says No, it callsconfirm_requirements(confirm=false)and continues requirement capture.
The server refuses to confirm requirements unless step 2 has happened first (prevents auto-confirm in the same turn as requirement capture).
Stage 1 Scope: This is the first development stage focusing on basic matching functionality and database task integration. Future stages will add more sophisticated features (to be specified later).
Key Architectural Decisions:
- Azure OpenAI integration: Server calls Azure OpenAI directly for extraction and embeddings (no sampling dependency)
- 10-tool workflow: Separate tools for task management (4), requirement gathering (3), search execution (1), and result refinement (2)
- Database task integration: Direct access to published tasks with skills from Beschaffungstool KMP
- Validation-only approach: Validation compares DB vs description but always uses DB skills for search
- Common extraction function:
_extract_requirements_from_description()as single source of truth (DRY principle) - Automatic task workflow:
find_capacities_for_task()fully automated with validation display - Task reference tracking: Search cache includes
task_idfield (null for ad-hoc, task ID for DB tasks) - Explicit confirmation: Requirements returned for user confirmation before search
- Session state: In-memory storage of requirements for update workflow
- Filter tracking: Filters stored within search cache using filter_id (not new search_id)
- Search sessions: Complete results stored server-side, accessed via search_id (60min expiry)
- Single query pattern: One JOIN query fetches all data, processed in Python
- Markdown output: All tables formatted as markdown for better client rendering
- No truncation: Full competence lists always shown
- No availability scoring: Availability is displayed and can be used as a date-range filter, but does not influence the score
- Weights: competence 0.8, role 0.2
- Fuzzy matching: Filter tool uses fuzzywuzzy for flexible result refinement
- LLM integration: Azure OpenAI (
gpt-4.1chat +text-embedding-3-large) with embedding cache; no heuristic fallback
Impact
- New capability:
capacity-matching- Core matching functionality with database task integration - New files:
database.toml- Database connection configurationarchitecture.md- Arc42 architecture documentation with ADRssrc/teamlandkarte_mcp/mcp_server.py- MCP server implementation (10 tools)src/teamlandkarte_mcp/database/trino_client.py- Trino client (capacity + task queries)src/teamlandkarte_mcp/matching/task_analyzer.py- Azure-based task analysissrc/matching/matcher.py- Matching algorithm with common extraction functionsrc/matching/scorer.py- Scoring logicsrc/cache/query_cache.py- Database query caching (12h TTL)src/cache/search_cache.py- Search results caching (60min TTL) with task_id trackingsrc/config.py- Configuration managementrequirements.txtor updatedpyproject.toml- Dependencies
- Modified files:
main.py- Launch MCP serverpyproject.toml- Add dependenciesREADME.md- Update with task management features, validation workflow
- Dependencies added:
mcp- Model Context Protocol SDKtrino- Trino/Presto database clientcachetools- Caching implementationfuzzywuzzy- Fuzzy string matching for filters
Security & Constraints
- Read-only operations: Server must NEVER modify database data
- Credential storage: Credentials are provided via environment variables
(recommended: local
.env):DATA_LAKE_USERNAME,DATA_LAKE_PASSWORD.database.tomlcontains non-secret connection settings and must not be committed. - Network security: Trino/Presto connection over port 8446
- Data filtering:
- Capacities: Only consider where
deletion_reason IS NULL - Tasks: Only consider where
status__c = "Veröffentlicht"
- Capacities: Only consider where
- LLM access: Not available in the current server runtime. If reintroduced, it must use a supported MCP API.
- SQL injection prevention: All queries use proper parameterization
- Validation scope: Comparison only (skills and dates), role not validated (not in DB yet)
Non-Goals (Future Stages)
- Advanced filtering options beyond fuzzy matching
- Capacity booking/reservation
- Task modification or status updates
- Historical analysis
- Integration with other systems
- Multi-language support
- Role storage in database (currently extracted from description)