This project installs Moodle and runs separate MCP and ADK/API agent services that work with Moodle through Moodle Web Services.
The first version supports two Moodle-backed user flows:
- Creator: create courses and add basic URL resources.
- Student: list and consume enrolled Moodle courses.
- Moodle, PostgreSQL, and Moodle cron can run on their own VM from
services/moodle/docker-compose.yml. - The MCP tools can run on a separate VM from
services/mcp/docker-compose.yml. - The ADK/API agents and chat UI can run on a separate VM from
services/agents/docker-compose.yml. - The root
docker-compose.ymlremains a local all-in-one developer stack with the same service boundaries. - The FastAPI app serves a simple web chat UI and calls an OpenAI-compatible LLM endpoint.
- Google ADK agent construction uses LiteLLM settings from Compose, so
LITELLM_PROVIDER=openaiandLITELLM_MODEL=gpt-4o-minibecomeopenai/gpt-4o-mini. - Google ADK also exposes an education orchestrator with specialist sub-agents and reusable education skills.
- Set
AGENT_RUNTIME=adkto make/api/chatcall the ADK education orchestrator; setAGENT_RUNTIME=legacyto use the original OpenAI-compatible tool loop. Both runtimes call Moodle only through MCP. - Moodle operations are implemented as narrow Python tool functions and exposed through the MCP server.
- Moodle users and configured creator IDs determine effective app roles; production should keep
ALLOW_USER_ID_OVERRIDE=false.
flowchart LR
userBrowser["Browser / Educator / Student"] --> agentsProxy["Agents VM Caddy Proxy"]
agentsProxy --> agentsApi["FastAPI Agents App"]
agentsApi -->|"POST /api/chat"| adkRuntime["AdkChatRuntime"]
adkRuntime --> adkRunner["Google ADK Runner"]
adkRunner --> orchestrator["education_orchestrator"]
orchestrator --> courseCreator["course_creator_agent"]
orchestrator --> assessmentBuilder["assessment_builder_agent"]
orchestrator --> studentTutor["student_tutor_agent"]
orchestrator --> adminEnrollment["admin_enrollment_agent"]
orchestrator --> progressMonitor["progress_monitor_agent"]
orchestrator --> contentCurator["content_curator_agent"]
orchestrator -->|"Bound ADK Moodle tools"| mcpProxy["MCP VM Caddy Proxy"]
courseCreator -->|"Bound ADK Moodle tools"| mcpProxy
assessmentBuilder -->|"Bound ADK Moodle tools"| mcpProxy
studentTutor -->|"Bound ADK Moodle tools"| mcpProxy
adminEnrollment -->|"Bound ADK Moodle tools"| mcpProxy
progressMonitor -->|"Bound ADK Moodle tools"| mcpProxy
contentCurator -->|"Bound ADK Moodle tools"| mcpProxy
mcpProxy --> mcpServer["Moodle MCP Server"]
mcpServer -->|"Moodle REST Web Services"| moodleProxy["Moodle VM Caddy Proxy"]
moodleProxy --> moodleApp["Moodle PHP / Apache"]
moodleApp --> postgresDb["PostgreSQL"]
moodleCron["Moodle Cron"] --> moodleApp
moodleApp --> moodleData["moodledata Volume"]
sequenceDiagram
actor User
participant Browser as Browser UI
participant API as FastAPI /api/chat
participant Runtime as AdkChatRuntime
participant Runner as Google ADK Runner
participant Orchestrator as education_orchestrator
participant Specialist as Specialist ADK Agent
participant Toolset as Bound ADK Moodle Tools
participant MCP as Moodle MCP Server
participant Moodle as Moodle Web Services
participant DB as PostgreSQL
User->>Browser: Submit education request
Browser->>API: POST /api/chat with message, role, user_id
API->>Runtime: chat(role, message, user_id)
Runtime->>Runner: run_async(new_message)
Runner->>Orchestrator: Invoke root agent
Orchestrator->>Specialist: Delegate to relevant education sub-agent
Specialist->>Toolset: Request Moodle tool when Moodle data or changes are needed
Toolset->>MCP: call_tool(name, arguments)
MCP->>Moodle: REST request to /webservice/rest/server.php
Moodle->>DB: Read or write Moodle state
DB-->>Moodle: Query result
Moodle-->>MCP: Web Services response
MCP-->>Toolset: MCP tool result
Toolset-->>Specialist: Tool output
Specialist-->>Orchestrator: Draft final answer
Orchestrator-->>Runner: Final ADK event
Runner-->>Runtime: Stream events
Runtime-->>API: ChatResult answer and event summaries
API-->>Browser: JSON response
Browser-->>User: Render agent response
-
Copy the environment template.
cp .env.example .env
-
Edit
.envand set the Moodle admin password, database password, app secret, LLM key, and hostnames.MOODLE_DOWNLOAD_URLcontrols which Moodle release tarball is baked into the local Moodle image. -
Start the local all-in-one stack.
docker compose up -d --build
-
Open Moodle and finish the initial setup.
http://moodle.localhostAfter you are logged in, use
http://moodle.localhostorhttp://moodle.localhost/my/. If you manually openhttp://moodle.localhost/login/index.phpwhile already logged in, Moodle shows a confirmation page asking whether to log out before logging in as another user. Use the explicithttp://URL for local development so it matches Moodle's configuredwwwrootand avoids proxy scheme redirects. -
Follow the Moodle Web Services setup guide in
deploy/moodle/SETUP.md. -
Add the generated Moodle token to
.envasMOODLE_TOKEN, then restart the MCP and agents services.docker compose up -d mcp agents
-
Open the chat app.
http://app.localhost
For a pure localhost route without custom hostnames, open http://localhost.
Use Python 3.12 or newer.
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev,adk]"
pytestRun the API locally:
uvicorn moodle_mcp.api:app --reloadRun the MCP server directly:
moodle-mcp-server --transport stdioRun a network MCP server locally:
moodle-mcp-server --transport streamable-http --host 0.0.0.0 --port 8000build_google_adk_agent() returns an education orchestrator backed by LiteLLM. When AGENT_RUNTIME=adk, the FastAPI /api/chat endpoint runs that orchestrator through a Google ADK Runner. The orchestrator delegates to specialist ADK sub-agents and connects to Moodle through bound ADK tools that call the MCP server at MCP_SERVER_URL. These tools inject the server-resolved Moodle role and user id into every MCP call.
Call chain:
Browser UI -> /api/chat -> AdkChatRuntime -> education_orchestrator -> specialist sub-agent -> Moodle MCP server -> Moodle Web Services
Specialist ADK agents:
course_creator_agent: plans and creates course shells, lessons, and starter resources.assessment_builder_agent: drafts quizzes, rubrics, assignments, and assessment plans.student_tutor_agent: helps learners understand visible Moodle course content.admin_enrollment_agent: guides enrollment, access, role, and cohort workflows.progress_monitor_agent: reviews engagement signals and recommends support interventions.content_curator_agent: recommends and places learning resources.
Education skills:
course-creation-skill: category discovery, course shell creation, section planning, URL resources.lesson-planning-skill: objectives, lesson outlines, activities, and Moodle-ready plans.assessment-builder-skill: quiz, question bank, rubric, and assignment drafts.student-tutor-skill: learner explanations, course summaries, and next study steps.admin-enrollment-skill: user access, enrollment, role, and cohort guidance.progress-engagement-skill: engagement review and at-risk learner support planning.content-curator-skill: resource recommendations and URL resource creation.support-assistant-skill: Moodle navigation, access troubleshooting, and setup support.
The current implemented Moodle tool surface supports course shells, URL resources, page resources, categories, user lookup, enrolled-course listing, course contents, and read-only activity completion status. Skills that need quizzes, assignments, grades, files, enrollment writes, cohorts, or reports are scaffolded with explicit future tool requirements.
The app expects Moodle REST Web Services to be enabled with these functions:
core_webservice_get_site_infocore_course_get_categoriescore_course_create_coursescore_course_get_contentscore_completion_get_activities_completion_statuscore_enrol_get_users_coursescore_user_get_users_by_fieldmod_page_add_instancemod_url_add_instance
The exact Moodle role capabilities still need to be configured inside Moodle. Creator users should only receive the course/category permissions they actually need.
Use one checkout of this repo per VM, then run the compose file for that VM:
- Moodle VM: create
services/moodle/.envfromservices/moodle/.env.example, then rundocker compose -f services/moodle/docker-compose.yml up -d --build. - Complete Moodle setup and create the Web Services token from
deploy/moodle/SETUP.md. - MCP VM: create
services/mcp/.envfromservices/mcp/.env.example, setMOODLE_BASE_URLto the Moodle VM URL andMOODLE_TOKENto the Web Services token, then rundocker compose -f services/mcp/docker-compose.yml up -d --build. - Agents VM: create
services/agents/.envfromservices/agents/.env.example, setMCP_SERVER_URLto the MCP VM endpoint, setLITELLM_API_KEY,LITELLM_PROVIDER,LITELLM_MODEL, andLITELLM_BASE_URL, then rundocker compose -f services/agents/docker-compose.yml up -d --build. - Configure backups for PostgreSQL and Moodle data volumes on the Moodle VM.
Only ports 80 and 443 should be exposed publicly on each VM. Database, Moodle container ports, agents ports, and raw MCP ports should remain on the Docker network or private VM network.
See docs/production-readiness.md for the production identity, authorization, and runtime checklist.
- Course creation, URL resources, page resources, user lookup, and completion reads are implemented first.
- File upload and richer Moodle activity creation are intentionally left behind capability checks because Moodle Web Services support varies by installation.
- The app resolves effective role server-side from
MOODLE_CREATOR_USER_IDS; production should keepALLOW_USER_ID_OVERRIDE=falseand replace this with Moodle capability checks when per-user auth is added.