MCP Hub
Back to servers

MCP Platform

A scalable execution platform that enables users to interact with HR, ERP, and DevOps domains through a chat interface powered by LlamaIndex and the Model Context Protocol. It provides a configuration-driven architecture for orchestrating LLM-suggested actions with authoritative tool execution and domain isolation.

Updated
Feb 21, 2026

MCP Platform

A scalable MCP-based execution platform that allows users to interact via a chat UI, with an LLM (via LlamaIndex) interpreting intent and controlled execution of application-specific actions via MCP.

Architecture Overview

┌─────────────┐
│   Chat UI   │  React-based frontend
└──────┬──────┘
       │
       ▼
┌─────────────────────────────┐
│  Orchestrator (AI Gateway)  │  FastAPI - Conversation management, LLM orchestration
└──────┬──────────────────────┘
       │
       ├────────────────────┐
       ▼                    ▼
┌─────────────┐      ┌─────────────┐
│     LLM     │      │ MCP Client  │
│ (LlamaIndex)│      │             │
└─────────────┘      └──────┬──────┘
                            │
                            ▼
                     ┌─────────────┐
                     │ MCP Server  │  Tool registry, auth, audit, routing
                     └──────┬──────┘
                            │
          ┌─────────────────┼─────────────────┐
          ▼                 ▼                 ▼
    ┌───────────┐    ┌───────────┐    ┌───────────┐
    │    HR     │    │    ERP    │    │  DevOps   │
    │  Domain   │    │  Domain   │    │  Domain   │
    └───────────┘    └───────────┘    └───────────┘

Key Principles

  • Separation of Concerns: Each component has a single responsibility
  • Domain Isolation: Applications are isolated with no cross-domain calls
  • Configuration-Driven: New domains added via configuration, not code changes
  • LLM is Advisory, MCP is Authoritative: LLM suggests actions, MCP enforces them

Components

Frontend (Chat UI)

  • Captures user input
  • Displays assistant responses
  • No business logic
  • No direct LLM or MCP access

Orchestrator (AI Gateway)

  • Manages conversation state
  • Interfaces with LLM via LlamaIndex
  • Supplies tool definitions to LLM
  • Parses structured tool calls
  • Invokes MCP Client

MCP Server

  • Registers and exposes MCP tools
  • Enforces authorization
  • Routes calls to application domains
  • Audits all executions
  • No LLM or UI logic

Application Domains

Each domain contains:

  • Tool definitions (namespaced, e.g., hr.get_employee)
  • Adapter implementation
  • Permission model
  • Configuration

Included domains:

  • HR: Employee lookup, department info
  • ERP: Invoices, inventory management
  • DevOps: Kubernetes operations, logs, scaling

Quick Start

Prerequisites

  • Python 3.10+
  • Node.js 18+
  • Docker (optional)

Local Development

  1. Clone and setup:
cd mcp_poc
cp .env.example .env
# Edit .env with your LLM API keys
  1. Install Python dependencies:
pip install -e ".[dev]"
  1. Start MCP Server (terminal 1):
export PYTHONPATH=$PWD/src
python -m mcp_server.main
  1. Start Orchestrator (terminal 2):
export PYTHONPATH=$PWD/src
python -m orchestrator.main
  1. Start Frontend (terminal 3):
cd frontend
npm install
npm run dev
  1. Open browser: http://localhost:3000

Using Docker

# Build and run all services
docker-compose up --build

# Access:
# - Frontend: http://localhost:3000
# - Orchestrator API: http://localhost:8000
# - MCP Server API: http://localhost:8001

Testing with Mock LLM

For testing without LLM API keys, use the mock provider:

# config/settings.yaml
llm:
  provider: mock

API Endpoints

Orchestrator (port 8000)

EndpointMethodDescription
/healthGETHealth check
/chatPOSTSend chat message
/conversationsGETList conversations
/conversations/{id}GETGet conversation history
/conversations/{id}DELETEDelete conversation
/toolsGETList available tools

MCP Server (port 8001)

EndpointMethodDescription
/healthGETHealth check
/toolsGETList registered tools
/tools/{name}GETGet tool details
/executePOSTExecute a tool
/domainsGETList registered domains

Tool Examples

HR Domain

# Get employee information
hr.get_employee(employee_id="E001")

# Search employees
hr.search_employees(department="Engineering", query="developer")

# List departments
hr.list_departments()

ERP Domain

# Get invoice
erp.get_invoice(invoice_id="INV-001")

# Create invoice
erp.create_invoice(
    customer="Acme Corp",
    items=[{"description": "Service", "quantity": 1, "unit_price": 1000}]
)

# Check low stock
erp.check_low_stock(category="Components")

DevOps Domain

# List pods
devops.list_pods(namespace="production")

# Get pod logs
devops.get_pod_logs(pod_name="api-server-xyz")

# Scale deployment
devops.scale_deployment(deployment_name="api-server", replicas=3)

Adding a New Domain

  1. Create domain directory:
src/domains/mydomain/
├── __init__.py
└── config.yaml (optional)
  1. Implement adapter:
# src/domains/mydomain/__init__.py
from domains.base import BaseAdapter
from shared.models import DomainConfig, ToolDefinition

class MyDomainAdapter(BaseAdapter):
    def __init__(self, config: DomainConfig):
        super().__init__(config)
        self._define_tools()
    
    def _define_tools(self):
        self._tools["my_action"] = ToolDefinition(
            name="my_action",
            domain="mydomain",
            description="Does something useful",
            input_schema={...},
            output_schema={...}
        )
    
    @property
    def tools(self):
        return list(self._tools.values())
    
    def execute(self, action, parameters, context):
        # Implement action handlers
        ...

def register_mydomain_domain(router):
    config = DomainConfig(name="mydomain", ...)
    adapter = MyDomainAdapter(config)
    
    from mcp_server.registry import get_registry
    get_registry().register_many(adapter.tools)
    router.register_adapter("mydomain", adapter.execute)
  1. Register in domains/__init__.py:
from domains.mydomain import register_mydomain_domain

def load_all_domains(router):
    # ... existing domains ...
    register_mydomain_domain(router)
  1. Add configuration (optional):
# config/domains/mydomain.yaml
name: mydomain
description: My custom domain
version: "1.0.0"
enabled: true

Configuration

Environment Variables

VariableDescriptionDefault
MCP_ENVIRONMENTEnvironment namedevelopment
MCP_LOG_LEVELLog levelINFO
LLM_PROVIDERLLM providerazure_openai
LLM_API_KEYAPI key for LLM-
LLM_API_BASEAPI base URL-
LLM_MODELModel namegpt-4
MCP_SERVER_PORTMCP Server port8001
ORCHESTRATOR_PORTOrchestrator port8000

YAML Configuration

See config/settings.yaml for full configuration options.

Security

Authentication

  • User identity originates in Orchestrator
  • MCP Server trusts only authenticated MCP Clients
  • JWT-based token authentication

Authorization

  • Enforced in MCP Server
  • Never decided by the LLM
  • Role-based and scope-based access control

Auditing

  • All tool executions are logged
  • Captures: user, tool, parameters, timestamp, result
  • Sensitive parameters are automatically redacted

Testing

# Run all tests
pytest

# Run with coverage
pytest --cov=src --cov-report=html

# Run specific test file
pytest tests/test_domains.py

# Run specific test
pytest tests/test_mcp_server.py::TestToolRegistry::test_register_tool

Project Structure

mcp_poc/
├── src/
│   ├── shared/              # Shared models, config, utilities
│   │   ├── models.py        # Pydantic models
│   │   ├── config.py        # Configuration management
│   │   ├── logging.py       # Structured logging
│   │   └── schema.py        # JSON Schema utilities
│   ├── mcp_server/          # MCP Server
│   │   ├── main.py          # FastAPI app
│   │   ├── registry.py      # Tool registry
│   │   ├── router.py        # Tool routing
│   │   ├── auth.py          # Authentication/Authorization
│   │   └── audit.py         # Audit logging
│   ├── mcp_client/          # MCP Client
│   │   ├── client.py        # HTTP client
│   │   └── discovery.py     # Tool discovery with caching
│   ├── orchestrator/        # AI Gateway
│   │   ├── main.py          # FastAPI app
│   │   ├── llm.py           # LLM providers (LlamaIndex)
│   │   ├── conversation.py  # Conversation management
│   │   └── gateway.py       # Core orchestration logic
│   └── domains/             # Application domains
│       ├── base.py          # Base adapter classes
│       ├── hr/              # HR domain
│       ├── erp/             # ERP domain
│       └── devops/          # DevOps domain
├── frontend/                # React chat UI
│   ├── src/
│   │   ├── App.tsx          # Main component
│   │   └── services/api.ts  # API client
│   └── package.json
├── config/                  # Configuration files
│   ├── settings.yaml        # Main config
│   └── domains/             # Domain configs
├── tests/                   # Test suite
├── docker-compose.yml       # Docker orchestration
├── Dockerfile              # Backend container
└── pyproject.toml          # Python project config

Success Criteria

✅ New applications onboarded via new domain only
✅ No core redeployment for extensions
✅ LLM provider swappable without MCP changes
✅ Safe coexistence of multiple applications
✅ Domain isolation by design
✅ Configuration-driven extensibility

License

MIT License - see LICENSE for details.

Reviews

No reviews yet

Sign in to write a review