maple-mcp 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. maple_mcp-0.1.0/.env.example +16 -0
  2. maple_mcp-0.1.0/.github/workflows/publish.yml +22 -0
  3. maple_mcp-0.1.0/.github/workflows/test.yml +68 -0
  4. maple_mcp-0.1.0/.gitignore +37 -0
  5. maple_mcp-0.1.0/LICENSE +21 -0
  6. maple_mcp-0.1.0/PKG-INFO +162 -0
  7. maple_mcp-0.1.0/README.md +118 -0
  8. maple_mcp-0.1.0/docker-compose.ci.yaml +100 -0
  9. maple_mcp-0.1.0/examples/block_sorting/.env.example +18 -0
  10. maple_mcp-0.1.0/examples/block_sorting/README.md +99 -0
  11. maple_mcp-0.1.0/examples/block_sorting/default.node.info.yaml +124 -0
  12. maple_mcp-0.1.0/examples/block_sorting/default.node.yaml +7 -0
  13. maple_mcp-0.1.0/examples/block_sorting/maple.config.yaml +26 -0
  14. maple_mcp-0.1.0/examples/block_sorting/mock_agent.py +208 -0
  15. maple_mcp-0.1.0/examples/block_sorting/stub_node.py +166 -0
  16. maple_mcp-0.1.0/examples/block_sorting/vision.py +54 -0
  17. maple_mcp-0.1.0/figures/architecture-1.png +0 -0
  18. maple_mcp-0.1.0/figures/architecture.tex +62 -0
  19. maple_mcp-0.1.0/maple/__init__.py +3 -0
  20. maple_mcp-0.1.0/maple/attach.py +128 -0
  21. maple_mcp-0.1.0/maple/auth.py +63 -0
  22. maple_mcp-0.1.0/maple/cli.py +220 -0
  23. maple_mcp-0.1.0/maple/config.py +189 -0
  24. maple_mcp-0.1.0/maple/hooks.py +37 -0
  25. maple_mcp-0.1.0/maple/middleware.py +42 -0
  26. maple_mcp-0.1.0/maple/models.py +40 -0
  27. maple_mcp-0.1.0/maple/operator/__init__.py +1 -0
  28. maple_mcp-0.1.0/maple/operator/agent.py +292 -0
  29. maple_mcp-0.1.0/maple/operator/prompt.md +48 -0
  30. maple_mcp-0.1.0/maple/operator/server.py +511 -0
  31. maple_mcp-0.1.0/maple/overseer/__init__.py +1 -0
  32. maple_mcp-0.1.0/maple/overseer/agent.py +213 -0
  33. maple_mcp-0.1.0/maple/overseer/prompt.md +56 -0
  34. maple_mcp-0.1.0/maple/overseer/server.py +429 -0
  35. maple_mcp-0.1.0/maple/services.py +229 -0
  36. maple_mcp-0.1.0/maple/sessions.py +184 -0
  37. maple_mcp-0.1.0/maple/tui.py +273 -0
  38. maple_mcp-0.1.0/maple/vision.py +58 -0
  39. maple_mcp-0.1.0/maple.config.example.yaml +24 -0
  40. maple_mcp-0.1.0/pyproject.toml +74 -0
  41. maple_mcp-0.1.0/tests/__init__.py +0 -0
  42. maple_mcp-0.1.0/tests/conftest.py +73 -0
  43. maple_mcp-0.1.0/tests/fixtures/custom_prompt.md +2 -0
  44. maple_mcp-0.1.0/tests/fixtures/custom_tool.py +10 -0
  45. maple_mcp-0.1.0/tests/fixtures/maple.config.yaml +10 -0
  46. maple_mcp-0.1.0/tests/test_cli.py +81 -0
  47. maple_mcp-0.1.0/tests/test_config.py +159 -0
  48. maple_mcp-0.1.0/tests/test_integration_custom.py +105 -0
  49. maple_mcp-0.1.0/tests/test_integration_full.py +371 -0
  50. maple_mcp-0.1.0/tests/test_integration_stub.py +227 -0
  51. maple_mcp-0.1.0/tests/test_overseer.py +117 -0
  52. maple_mcp-0.1.0/tests/test_sessions.py +210 -0
  53. maple_mcp-0.1.0/tests/test_tui.py +41 -0
@@ -0,0 +1,16 @@
1
+ # MADSci Service URLs
2
+ WORKCELL_SERVER_URL=http://localhost:8005/
3
+ DATA_SERVER_URL=http://localhost:8004/
4
+ EVENT_SERVER_URL=http://localhost:8001/
5
+ EXPERIMENT_SERVER_URL=http://localhost:8002/
6
+
7
+ # LLM Backend (pick one)
8
+ MODEL_PROVIDER=openai
9
+ OPENAI_API_KEY=sk-...
10
+ # MODEL_PROVIDER=anthropic
11
+ # ANTHROPIC_API_KEY=sk-ant-...
12
+ # MODEL_PROVIDER=ollama
13
+ # OLLAMA_HOST=http://localhost:11434
14
+
15
+ # Agent model (override per-agent if needed)
16
+ EXECUTOR_AGENT_MODEL=gpt-4o
@@ -0,0 +1,22 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ jobs:
8
+ publish:
9
+ runs-on: ubuntu-latest
10
+ permissions:
11
+ id-token: write
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+ - uses: actions/setup-python@v5
15
+ with:
16
+ python-version: "3.11"
17
+ - name: Install build tools
18
+ run: pip install build
19
+ - name: Build package
20
+ run: python -m build
21
+ - name: Publish to PyPI
22
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,68 @@
1
+ name: Tests
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ paths-ignore:
7
+ - '**.md'
8
+ - 'figures/**'
9
+ - 'LICENSE'
10
+ pull_request:
11
+ branches: [main]
12
+ paths-ignore:
13
+ - '**.md'
14
+ - 'figures/**'
15
+ - 'LICENSE'
16
+
17
+ jobs:
18
+ unit:
19
+ runs-on: ubuntu-latest
20
+ strategy:
21
+ matrix:
22
+ python-version: ["3.10", "3.11", "3.12"]
23
+ steps:
24
+ - uses: actions/checkout@v4
25
+ - uses: actions/setup-python@v5
26
+ with:
27
+ python-version: ${{ matrix.python-version }}
28
+ - name: Install dependencies
29
+ run: pip install -e ".[dev]"
30
+ - name: Run unit tests
31
+ run: pytest -m "not integration" --tb=short
32
+
33
+ integration:
34
+ runs-on: ubuntu-latest
35
+ needs: unit
36
+ steps:
37
+ - uses: actions/checkout@v4
38
+ - uses: actions/setup-python@v5
39
+ with:
40
+ python-version: "3.11"
41
+ - name: Install dependencies
42
+ run: pip install -e ".[dev]"
43
+
44
+ - name: Start MADSci services
45
+ run: |
46
+ docker compose -f docker-compose.ci.yaml up -d
47
+ echo "Waiting for services to be ready..."
48
+ sleep 20
49
+
50
+ - name: Verify services are up
51
+ run: |
52
+ curl -sf http://localhost:8001/health || (echo "Event Manager not ready" && exit 1)
53
+ curl -sf http://localhost:8005/health || (echo "Workcell Manager not ready" && exit 1)
54
+ echo "✓ MADSci services ready"
55
+
56
+ - name: Create .env for integration tests
57
+ run: |
58
+ printf 'WORKCELL_SERVER_URL=http://localhost:8005/\nEXPERIMENT_SERVER_URL=http://localhost:8002/\nEVENT_SERVER_URL=http://localhost:8001/\nDATA_SERVER_URL=http://localhost:8004/\nRESOURCE_SERVER_URL=http://localhost:8003/\nLOCATION_SERVER_URL=http://localhost:8006/\nMCP_OPERATOR_URL=http://localhost:8102/mcp\n' > examples/block_sorting/.env
59
+ cp examples/block_sorting/.env .env
60
+
61
+ - name: Run integration tests
62
+ run: pytest -m integration --tb=short
63
+
64
+ - name: Tear down
65
+ if: always()
66
+ run: |
67
+ maple down
68
+ docker compose -f docker-compose.ci.yaml down -v
@@ -0,0 +1,37 @@
1
+ # Specs (internal planning docs)
2
+ specs/
3
+
4
+ # Python
5
+ __pycache__/
6
+ *.py[cod]
7
+ *$py.class
8
+ *.egg-info/
9
+ dist/
10
+ build/
11
+ .eggs/
12
+
13
+ # Virtual environment
14
+ .venv/
15
+ venv/
16
+ env/
17
+
18
+ # IDE
19
+ .idea/
20
+ .vscode/
21
+ *.swp
22
+ *.swo
23
+
24
+ # OS
25
+ .DS_Store
26
+ Thumbs.db
27
+
28
+ # Environment
29
+ .env
30
+
31
+ # Sessions
32
+ sessions/
33
+
34
+ # Test artifacts
35
+ .pytest_cache/
36
+ .coverage
37
+ htmlcov/
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Gabriel Ferrer
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,162 @@
1
+ Metadata-Version: 2.5
2
+ Name: maple-mcp
3
+ Version: 0.1.0
4
+ Summary: Model-Agnostic Platform for Laboratory Experiments — LLM agents for autonomous MADSci experiments via MCP
5
+ Project-URL: Homepage, https://github.com/gabrielferrer/maple-mcp
6
+ Project-URL: Repository, https://github.com/gabrielferrer/maple-mcp
7
+ Project-URL: Issues, https://github.com/gabrielferrer/maple-mcp/issues
8
+ Author: Gabriel Ferrer
9
+ License: MIT
10
+ License-File: LICENSE
11
+ Keywords: agents,autonomous-lab,llm,madsci,mcp,robotics
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Scientific/Engineering
20
+ Requires-Python: >=3.10
21
+ Requires-Dist: fastapi>=0.100.0
22
+ Requires-Dist: fastmcp>=2.0.0
23
+ Requires-Dist: httpx>=0.24.0
24
+ Requires-Dist: madsci-client<0.6.0,>=0.5.0
25
+ Requires-Dist: madsci-common<0.6.0,>=0.5.0
26
+ Requires-Dist: madsci-experiment-application<0.6.0,>=0.5.0
27
+ Requires-Dist: madsci-node-module<0.6.0,>=0.5.0
28
+ Requires-Dist: numpy>=1.24.0
29
+ Requires-Dist: openai>=1.0.0
30
+ Requires-Dist: python-dotenv>=1.0.0
31
+ Requires-Dist: pyyaml>=6.0
32
+ Requires-Dist: rich>=13.0.0
33
+ Requires-Dist: strands-agents[anthropic,ollama]>=1.0.0
34
+ Requires-Dist: textual>=4.0.0
35
+ Requires-Dist: typer>=0.9.0
36
+ Requires-Dist: uvicorn>=0.20.0
37
+ Requires-Dist: watchfiles>=0.20.0
38
+ Provides-Extra: dev
39
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
40
+ Requires-Dist: pytest-mock>=3.10.0; extra == 'dev'
41
+ Requires-Dist: pytest>=7.0.0; extra == 'dev'
42
+ Requires-Dist: ruff>=0.1.0; extra == 'dev'
43
+ Description-Content-Type: text/markdown
44
+
45
+ # MAPLE
46
+
47
+ **Model-Agnostic Platform for Laboratory Experiments**
48
+
49
+ MAPLE adds LLM agent capabilities to any [MADSci](https://github.com/AD-SDL/MADSci)-powered laboratory (v0.5.x) via MCP. Two agents — an **Operator** for experiment execution and an **Overseer** for lab monitoring — connect to your lab through configurable MCP servers.
50
+
51
+ ## Architecture
52
+
53
+ ![MAPLE Architecture](figures/architecture-1.png)
54
+
55
+ ## Quick Start
56
+
57
+ ```bash
58
+ pip install maple-mcp
59
+ cd your-experiment/
60
+ cp .env.example .env # Configure MADSci URLs + model provider
61
+ maple serve stub # Start demo (no LLM needed)
62
+ maple chat operator # Open TUI — type anything
63
+ maple down # Stop all services
64
+ ```
65
+
66
+ For a real LLM experiment:
67
+ ```bash
68
+ maple serve operator # Start with your configured model
69
+ maple chat operator # Run an experiment
70
+ maple chat operator --resume # Pick up where you left off
71
+ ```
72
+
73
+ See [`examples/block_sorting/`](examples/block_sorting/) for a complete walkthrough.
74
+
75
+ ## Installation
76
+
77
+ ```bash
78
+ pip install maple-mcp
79
+ ```
80
+
81
+ Requires Python 3.10+ and a running [MADSci](https://github.com/AD-SDL/MADSci) lab (v0.5.x).
82
+
83
+ ## CLI
84
+
85
+ ```
86
+ maple serve {all, operator, overseer, stub, mock} [--dev]
87
+ maple chat {operator, overseer} [--resume]
88
+ maple down
89
+ maple status
90
+ maple logs
91
+ ```
92
+
93
+ ## Configuration
94
+
95
+ One `maple.config.yaml` per experiment:
96
+
97
+ ```yaml
98
+ experiment:
99
+ name: My Experiment
100
+ objective: Sort samples by type
101
+ constraints:
102
+ - "Only handle one sample at a time"
103
+
104
+ operator:
105
+ vision_backend: "vision:MyVision"
106
+ custom_tools:
107
+ - "my_tools:prepare_sample"
108
+ post_action_hooks:
109
+ - node: AnalysisNode
110
+ action: verify_placement
111
+ ```
112
+
113
+ Infrastructure goes in `.env` (IPs, API keys, model provider).
114
+
115
+ ## Extending MAPLE
116
+
117
+ | Extension Point | Mechanism | Config Key |
118
+ |---|---|---|
119
+ | Vision detection | Subclass `VisionBackend` | `operator.vision_backend` |
120
+ | MCP tools | `@mcp.tool` decorator | `operator.custom_tools` / `overseer.custom_tools` |
121
+ | Agent hooks | `extra_hooks` param on factory | Programmatic |
122
+ | Post-action hooks | YAML (no code) | `operator.post_action_hooks` |
123
+ | System prompts | Markdown file | `operator.prompt` / `overseer.prompt` |
124
+
125
+ ## Supported Models
126
+
127
+ | Provider | Environment Variable |
128
+ |---|---|
129
+ | OpenAI | `MODEL_PROVIDER=openai` |
130
+ | Anthropic | `MODEL_PROVIDER=anthropic` |
131
+ | Ollama (local, free) | `MODEL_PROVIDER=ollama` |
132
+
133
+ ## Multi-User
134
+
135
+ Each device auto-generates a unique identity token. Multiple users can run experiments simultaneously — sessions are isolated automatically.
136
+
137
+ ## Programmatic Usage
138
+
139
+ ```python
140
+ from maple.operator.agent import create_operator_agent
141
+
142
+ agent = create_operator_agent("my-session")
143
+ result = agent("Sort the colored blocks by color.")
144
+ ```
145
+
146
+ ## Testing
147
+
148
+ ```bash
149
+ pytest -m "not integration" # Unit tests (no network)
150
+ docker compose -f docker-compose.ci.yaml up -d # Start MADSci
151
+ pytest -m integration # Integration tests
152
+ ```
153
+
154
+ ## Compatibility
155
+
156
+ - Python 3.10+
157
+ - MADSci >=0.5.0, <0.6.0
158
+ - FastMCP 3.x
159
+
160
+ ## License
161
+
162
+ [MIT](LICENSE)
@@ -0,0 +1,118 @@
1
+ # MAPLE
2
+
3
+ **Model-Agnostic Platform for Laboratory Experiments**
4
+
5
+ MAPLE adds LLM agent capabilities to any [MADSci](https://github.com/AD-SDL/MADSci)-powered laboratory (v0.5.x) via MCP. Two agents — an **Operator** for experiment execution and an **Overseer** for lab monitoring — connect to your lab through configurable MCP servers.
6
+
7
+ ## Architecture
8
+
9
+ ![MAPLE Architecture](figures/architecture-1.png)
10
+
11
+ ## Quick Start
12
+
13
+ ```bash
14
+ pip install maple-mcp
15
+ cd your-experiment/
16
+ cp .env.example .env # Configure MADSci URLs + model provider
17
+ maple serve stub # Start demo (no LLM needed)
18
+ maple chat operator # Open TUI — type anything
19
+ maple down # Stop all services
20
+ ```
21
+
22
+ For a real LLM experiment:
23
+ ```bash
24
+ maple serve operator # Start with your configured model
25
+ maple chat operator # Run an experiment
26
+ maple chat operator --resume # Pick up where you left off
27
+ ```
28
+
29
+ See [`examples/block_sorting/`](examples/block_sorting/) for a complete walkthrough.
30
+
31
+ ## Installation
32
+
33
+ ```bash
34
+ pip install maple-mcp
35
+ ```
36
+
37
+ Requires Python 3.10+ and a running [MADSci](https://github.com/AD-SDL/MADSci) lab (v0.5.x).
38
+
39
+ ## CLI
40
+
41
+ ```
42
+ maple serve {all, operator, overseer, stub, mock} [--dev]
43
+ maple chat {operator, overseer} [--resume]
44
+ maple down
45
+ maple status
46
+ maple logs
47
+ ```
48
+
49
+ ## Configuration
50
+
51
+ One `maple.config.yaml` per experiment:
52
+
53
+ ```yaml
54
+ experiment:
55
+ name: My Experiment
56
+ objective: Sort samples by type
57
+ constraints:
58
+ - "Only handle one sample at a time"
59
+
60
+ operator:
61
+ vision_backend: "vision:MyVision"
62
+ custom_tools:
63
+ - "my_tools:prepare_sample"
64
+ post_action_hooks:
65
+ - node: AnalysisNode
66
+ action: verify_placement
67
+ ```
68
+
69
+ Infrastructure goes in `.env` (IPs, API keys, model provider).
70
+
71
+ ## Extending MAPLE
72
+
73
+ | Extension Point | Mechanism | Config Key |
74
+ |---|---|---|
75
+ | Vision detection | Subclass `VisionBackend` | `operator.vision_backend` |
76
+ | MCP tools | `@mcp.tool` decorator | `operator.custom_tools` / `overseer.custom_tools` |
77
+ | Agent hooks | `extra_hooks` param on factory | Programmatic |
78
+ | Post-action hooks | YAML (no code) | `operator.post_action_hooks` |
79
+ | System prompts | Markdown file | `operator.prompt` / `overseer.prompt` |
80
+
81
+ ## Supported Models
82
+
83
+ | Provider | Environment Variable |
84
+ |---|---|
85
+ | OpenAI | `MODEL_PROVIDER=openai` |
86
+ | Anthropic | `MODEL_PROVIDER=anthropic` |
87
+ | Ollama (local, free) | `MODEL_PROVIDER=ollama` |
88
+
89
+ ## Multi-User
90
+
91
+ Each device auto-generates a unique identity token. Multiple users can run experiments simultaneously — sessions are isolated automatically.
92
+
93
+ ## Programmatic Usage
94
+
95
+ ```python
96
+ from maple.operator.agent import create_operator_agent
97
+
98
+ agent = create_operator_agent("my-session")
99
+ result = agent("Sort the colored blocks by color.")
100
+ ```
101
+
102
+ ## Testing
103
+
104
+ ```bash
105
+ pytest -m "not integration" # Unit tests (no network)
106
+ docker compose -f docker-compose.ci.yaml up -d # Start MADSci
107
+ pytest -m integration # Integration tests
108
+ ```
109
+
110
+ ## Compatibility
111
+
112
+ - Python 3.10+
113
+ - MADSci >=0.5.0, <0.6.0
114
+ - FastMCP 3.x
115
+
116
+ ## License
117
+
118
+ [MIT](LICENSE)
@@ -0,0 +1,100 @@
1
+ name: maple_ci
2
+
3
+ # Minimal MADSci stack for MAPLE integration tests.
4
+ # No lab dashboard, no minio — just the managers needed for E2E testing.
5
+
6
+ x-madsci-service: &madsci-service
7
+ image: ghcr.io/ad-sdl/madsci:v0.5.0
8
+ network_mode: host
9
+ extra_hosts:
10
+ - "host.docker.internal:host-gateway"
11
+ environment:
12
+ - USER_ID=1000
13
+ - GROUP_ID=1000
14
+ restart: "no"
15
+
16
+ services:
17
+ # === DATABASES ===
18
+
19
+ mongodb:
20
+ container_name: mongodb
21
+ image: mongo:8.0
22
+ network_mode: host
23
+ volumes:
24
+ - mongodb_data:/data/db
25
+
26
+ redis:
27
+ container_name: redis
28
+ image: redis:7.4
29
+ network_mode: host
30
+ command: redis-server --appendonly yes
31
+
32
+ postgres:
33
+ container_name: postgres
34
+ image: postgres:17
35
+ network_mode: host
36
+ environment:
37
+ - POSTGRES_USER=madsci
38
+ - POSTGRES_PASSWORD=madsci
39
+ - POSTGRES_DB=resources
40
+
41
+ # === MANAGERS ===
42
+
43
+ event_manager:
44
+ <<: *madsci-service
45
+ container_name: event_manager
46
+ command: python -m madsci.event_manager.event_server --host 0.0.0.0 --port 8001
47
+ depends_on:
48
+ - mongodb
49
+
50
+ resource_manager:
51
+ <<: *madsci-service
52
+ container_name: resource_manager
53
+ command: python -m madsci.resource_manager.resource_server --host 0.0.0.0 --port 8003
54
+ depends_on:
55
+ - postgres
56
+ - event_manager
57
+
58
+ data_manager:
59
+ <<: *madsci-service
60
+ container_name: data_manager
61
+ command: python -m madsci.data_manager.data_server --host 0.0.0.0 --port 8004
62
+ depends_on:
63
+ - mongodb
64
+ - event_manager
65
+
66
+ experiment_manager:
67
+ <<: *madsci-service
68
+ container_name: experiment_manager
69
+ command: python -m madsci.experiment_manager.experiment_server --host 0.0.0.0 --port 8002
70
+ depends_on:
71
+ - mongodb
72
+ - event_manager
73
+
74
+ workcell_manager:
75
+ <<: *madsci-service
76
+ container_name: workcell_manager
77
+ command: python -m madsci.workcell_manager.workcell_server --host 0.0.0.0 --port 8005
78
+ environment:
79
+ - USER_ID=1000
80
+ - GROUP_ID=1000
81
+ - LOCATION_SERVER_URL=http://localhost:8006/
82
+ - RESOURCE_SERVER_URL=http://localhost:8003/
83
+ - EVENT_SERVER_URL=http://localhost:8001/
84
+ - DATA_SERVER_URL=http://localhost:8004/
85
+ depends_on:
86
+ - redis
87
+ - mongodb
88
+ - resource_manager
89
+ - event_manager
90
+ - postgres
91
+
92
+ location_manager:
93
+ <<: *madsci-service
94
+ container_name: location_manager
95
+ command: python -m madsci.location_manager.location_server --host 0.0.0.0 --port 8006
96
+ depends_on:
97
+ - redis
98
+
99
+ volumes:
100
+ mongodb_data:
@@ -0,0 +1,18 @@
1
+ # Environment variables for the block sorting demo.
2
+ # Copy to .env and adjust as needed.
3
+
4
+ # MADSci service URLs
5
+ WORKCELL_SERVER_URL=http://localhost:8005/
6
+ EXPERIMENT_SERVER_URL=http://localhost:8002/
7
+ EVENT_SERVER_URL=http://localhost:8001/
8
+ DATA_SERVER_URL=http://localhost:8004/
9
+ RESOURCE_SERVER_URL=http://localhost:8003/
10
+ LOCATION_SERVER_URL=http://localhost:8006/
11
+
12
+ # MCP server URL (Operator)
13
+ MCP_OPERATOR_URL=http://localhost:8102/mcp
14
+
15
+ # Model provider (not needed for mock agent demo)
16
+ # MODEL_PROVIDER=ollama
17
+ # OLLAMA_HOST=http://localhost:11434
18
+ # OPERATOR_MODEL=qwen3:8b
@@ -0,0 +1,99 @@
1
+ # Block Sorting Demo
2
+
3
+ A self-contained example demonstrating the full MAPLE pipeline. Uses a stub robot node, mock agent (no LLM needed), and an example VisionBackend.
4
+
5
+ ## What's Included
6
+
7
+ | File | Purpose |
8
+ |------|---------|
9
+ | `vision.py` | `ExampleVision` — hardcoded VisionBackend (3 blocks, always sorted) |
10
+ | `stub_node.py` | Minimal MADSci node with `pick_and_place` action |
11
+ | `mock_agent.py` | Scripted agent — walks through full experiment without an LLM |
12
+ | `maple.config.yaml` | MAPLE config pointing to `vision:ExampleVision` |
13
+ | `.env.example` | Template for service URLs |
14
+
15
+ ## Prerequisites
16
+
17
+ - Python 3.10+
18
+ - `pip install maple-mcp`
19
+ - A running MADSci lab (real or example lab via `docker compose`)
20
+
21
+ ## Setup
22
+
23
+ ### 1. Configure environment
24
+
25
+ ```bash
26
+ cd examples/block_sorting
27
+ cp .env.example .env
28
+ ```
29
+
30
+ Edit `.env` with your MADSci service URLs. Set `NODE_URL` to the address the Workcell Manager can reach your stub node at.
31
+
32
+ ### 2. Start the stub node
33
+
34
+ ```bash
35
+ python stub_node.py
36
+ ```
37
+
38
+ You should see:
39
+ ```
40
+ ✓ Registered StubBot at <NODE_URL> with Workcell Manager
41
+ INFO: Uvicorn running on http://0.0.0.0:2000
42
+ ```
43
+
44
+ ### 3. Start the mock agent
45
+
46
+ ```bash
47
+ python mock_agent.py
48
+ ```
49
+
50
+ ### 4. Launch the TUI
51
+
52
+ In a separate terminal:
53
+
54
+ ```bash
55
+ maple chat --agent operator
56
+ ```
57
+
58
+ Type anything (e.g., "sort the blocks") and press Enter. The mock agent streams a scripted experiment:
59
+
60
+ 1. Registers the experiment
61
+ 2. Detects 3 blocks (2 red, 1 blue)
62
+ 3. Sorts each block with `pick_and_place`
63
+ 4. Verifies all blocks sorted
64
+ 5. Ends the experiment
65
+
66
+ Press Enter again to exit.
67
+
68
+ ## Cleanup
69
+
70
+ The stub node registers as non-permanent. To remove it, restart the Workcell Manager:
71
+
72
+ ```bash
73
+ docker restart workcell_manager
74
+ ```
75
+
76
+ ## Going Live
77
+
78
+ To use a real LLM instead of the mock agent:
79
+
80
+ 1. Install Ollama: `curl -fsSL https://ollama.com/install.sh | sh`
81
+ 2. Pull a model: `ollama pull qwen3:8b`
82
+ 3. Add to `.env`:
83
+ ```
84
+ MODEL_PROVIDER=ollama
85
+ OLLAMA_HOST=http://localhost:11434
86
+ OPERATOR_MODEL=qwen3:8b
87
+ ```
88
+ 4. Skip the mock agent — use `maple serve --agent operator --config maple.config.yaml` instead
89
+ 5. Run `maple chat --agent operator` and tell it: "Sort the blocks by color"
90
+
91
+ To use real hardware, replace `ExampleVision` with your own `VisionBackend` subclass and update `vision_backend` in `maple.config.yaml`.
92
+
93
+ ## Troubleshooting
94
+
95
+ | Problem | Solution |
96
+ |---------|----------|
97
+ | StubBot shows `ready=False` | Check the Workcell Manager can reach NODE_URL |
98
+ | Workflow stuck in "Queued" | Node isn't ready. Verify with `get_nodes()` |
99
+ | Node name already exists | Restart Workcell Manager to clear non-permanent nodes |