feat: add FreeCAD and Rommie MCP server configurations and deployment playbooks
This commit is contained in:
@@ -7,6 +7,8 @@
|
|||||||
agent_s_repo_dir: "{{github_repo_dir}}/Agent-S"
|
agent_s_repo_dir: "{{github_repo_dir}}/Agent-S"
|
||||||
pulse_xrdp_archive: "{{rel_dir}}/pulseaudio_module_xrdp_{{pulseaudio_module_xrdp_rel}}.tar"
|
pulse_xrdp_archive: "{{rel_dir}}/pulseaudio_module_xrdp_{{pulseaudio_module_xrdp_rel}}.tar"
|
||||||
pulse_xrdp_repo_dir: "{{github_repo_dir}}/pulseaudio-module-xrdp"
|
pulse_xrdp_repo_dir: "{{github_repo_dir}}/pulseaudio-module-xrdp"
|
||||||
|
rommie_archive: "{{rel_dir}}/rommie_{{rommie_rel}}.tar"
|
||||||
|
rommie_repo_dir: "{{repo_dir}}/rommie"
|
||||||
|
|
||||||
tasks:
|
tasks:
|
||||||
- name: Ensure release directory exists
|
- name: Ensure release directory exists
|
||||||
@@ -46,3 +48,19 @@
|
|||||||
ansible.builtin.command: git archive -o "{{pulse_xrdp_archive}}" "{{pulseaudio_module_xrdp_rel}}"
|
ansible.builtin.command: git archive -o "{{pulse_xrdp_archive}}" "{{pulseaudio_module_xrdp_rel}}"
|
||||||
args:
|
args:
|
||||||
chdir: "{{pulse_xrdp_repo_dir}}"
|
chdir: "{{pulse_xrdp_repo_dir}}"
|
||||||
|
|
||||||
|
# Rommie
|
||||||
|
- name: Fetch all remote branches and tags (rommie)
|
||||||
|
ansible.builtin.command: git fetch --all
|
||||||
|
args:
|
||||||
|
chdir: "{{rommie_repo_dir}}"
|
||||||
|
|
||||||
|
- name: Pull latest changes (rommie)
|
||||||
|
ansible.builtin.command: git pull
|
||||||
|
args:
|
||||||
|
chdir: "{{rommie_repo_dir}}"
|
||||||
|
|
||||||
|
- name: Create rommie archive for specified release
|
||||||
|
ansible.builtin.command: git archive -o "{{rommie_archive}}" "{{rommie_rel}}"
|
||||||
|
args:
|
||||||
|
chdir: "{{rommie_repo_dir}}"
|
||||||
|
|||||||
@@ -48,7 +48,7 @@
|
|||||||
- name: Ensure Python, Python Dev, Venv module is installed
|
- name: Ensure Python, Python Dev, Venv module is installed
|
||||||
become: true
|
become: true
|
||||||
ansible.builtin.apt:
|
ansible.builtin.apt:
|
||||||
name: [python3,python3-venv,python3-dev]
|
name: [python3,python3-venv,python3-dev, acl]
|
||||||
state: present
|
state: present
|
||||||
update_cache: true
|
update_cache: true
|
||||||
|
|
||||||
|
|||||||
21
ansible/freecad_mcp/.env.j2
Normal file
21
ansible/freecad_mcp/.env.j2
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# FreeCAD Robust MCP Server — Environment Configuration
|
||||||
|
# Managed by Ansible — do not edit manually
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# MCP Transport Configuration
|
||||||
|
# =============================================================================
|
||||||
|
FREECAD_TRANSPORT=http
|
||||||
|
FREECAD_HTTP_PORT={{ freecad_mcp_port }}
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# FreeCAD Connection Mode
|
||||||
|
# =============================================================================
|
||||||
|
FREECAD_MODE={{ freecad_mcp_mode | default('xmlrpc') }}
|
||||||
|
FREECAD_XMLRPC_HOST={{ freecad_mcp_xmlrpc_host | default('localhost') }}
|
||||||
|
FREECAD_XMLRPC_PORT={{ freecad_mcp_xmlrpc_port | default('9875') }}
|
||||||
|
FREECAD_TIMEOUT_MS={{ freecad_mcp_timeout_ms | default('30000') }}
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# Logging
|
||||||
|
# =============================================================================
|
||||||
|
FREECAD_LOG_LEVEL={{ freecad_mcp_log_level | default('INFO') }}
|
||||||
130
ansible/freecad_mcp/README.md
Normal file
130
ansible/freecad_mcp/README.md
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
# FreeCAD Robust MCP Server — Ansible Deployment
|
||||||
|
|
||||||
|
Deploys the [FreeCAD Robust MCP Server](https://pypi.org/project/freecad-robust-mcp/)
|
||||||
|
to Caliban as a systemd service with HTTP transport, ready for MCP Switchboard
|
||||||
|
consumption.
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────┐
|
||||||
|
│ caliban.incus │
|
||||||
|
│ │
|
||||||
|
│ ┌──────────────────────┐ │
|
||||||
|
│ │ freecad-mcp.service │ │
|
||||||
|
│ │ (streamable-http) │◄─── :22082 ──────────┤◄── MCP Switchboard
|
||||||
|
│ │ venv + PyPI package │ │ (oberon.incus)
|
||||||
|
│ └──────────────────────┘ │
|
||||||
|
│ │ │
|
||||||
|
│ │ xmlrpc :9875 │
|
||||||
|
│ ▼ │
|
||||||
|
│ ┌──────────────────────┐ │
|
||||||
|
│ │ FreeCAD (future) │ │
|
||||||
|
│ │ XML-RPC server │ │
|
||||||
|
│ └──────────────────────┘ │
|
||||||
|
└─────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- Caliban host in Ansible inventory (already exists in Ouranos)
|
||||||
|
- Python 3.11+ on Caliban (already present)
|
||||||
|
|
||||||
|
## Deployment
|
||||||
|
|
||||||
|
### 1. Copy playbook files to Ouranos
|
||||||
|
|
||||||
|
Copy the contents of this directory into your Ouranos repo:
|
||||||
|
|
||||||
|
```
|
||||||
|
ansible/freecad_mcp/
|
||||||
|
├── deploy.yml
|
||||||
|
├── .env.j2
|
||||||
|
└── freecad-mcp.service.j2
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Add inventory group
|
||||||
|
|
||||||
|
Add to `ansible/inventory/hosts`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
freecad_mcp:
|
||||||
|
hosts:
|
||||||
|
caliban.incus:
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Add host variables
|
||||||
|
|
||||||
|
Add to `ansible/inventory/host_vars/caliban.incus.yml`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# FreeCAD Robust MCP Server
|
||||||
|
freecad_mcp_user: harper
|
||||||
|
freecad_mcp_group: harper
|
||||||
|
freecad_mcp_directory: /srv/freecad-mcp
|
||||||
|
freecad_mcp_port: 22082
|
||||||
|
freecad_mcp_version: "0.5.0"
|
||||||
|
```
|
||||||
|
|
||||||
|
Update `services` list:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
- alloy
|
||||||
|
- caliban
|
||||||
|
- docker
|
||||||
|
- freecad_mcp
|
||||||
|
- kernos
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Run the playbook
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ansible-playbook freecad_mcp/deploy.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
## Upgrading
|
||||||
|
|
||||||
|
To upgrade to a new PyPI version, update `freecad_mcp_version` in host_vars
|
||||||
|
and re-run the playbook. The pip install task will detect the version change
|
||||||
|
and the handler will restart the service.
|
||||||
|
|
||||||
|
## Validation
|
||||||
|
|
||||||
|
The playbook automatically validates the deployment by:
|
||||||
|
|
||||||
|
1. Waiting for the HTTP port to become available
|
||||||
|
2. Sending an MCP `initialize` JSON-RPC request to `/mcp`
|
||||||
|
3. Verifying a 200 response
|
||||||
|
|
||||||
|
You can also manually test:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -X POST http://caliban.incus:22082/mcp \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"jsonrpc":"2.0","method":"initialize","id":1,"params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"curl","version":"1.0.0"}}}'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Service Management
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# On Caliban
|
||||||
|
sudo systemctl status freecad-mcp
|
||||||
|
sudo systemctl restart freecad-mcp
|
||||||
|
sudo journalctl -u freecad-mcp -f
|
||||||
|
```
|
||||||
|
|
||||||
|
## Security
|
||||||
|
|
||||||
|
The systemd service runs with hardened settings:
|
||||||
|
|
||||||
|
| Setting | Value | Rationale |
|
||||||
|
|---------|-------|-----------|
|
||||||
|
| `NoNewPrivileges` | `true` | No privilege escalation |
|
||||||
|
| `ProtectSystem` | `strict` | Filesystem is read-only except allowed paths |
|
||||||
|
| `ProtectHome` | `read-only` | Home directories protected |
|
||||||
|
| `PrivateTmp` | `true` | Isolated /tmp namespace |
|
||||||
|
| `ReadWritePaths` | `/srv/freecad-mcp` | Only app directory is writable |
|
||||||
|
|
||||||
|
This is significantly more hardened than the Kernos service (which needs
|
||||||
|
broad filesystem access for shell commands).
|
||||||
219
ansible/freecad_mcp/deploy.yml
Normal file
219
ansible/freecad_mcp/deploy.yml
Normal file
@@ -0,0 +1,219 @@
|
|||||||
|
---
|
||||||
|
# =============================================================================
|
||||||
|
# FreeCAD Robust MCP Server — Ansible Deployment Playbook
|
||||||
|
# =============================================================================
|
||||||
|
# Deploys the FreeCAD MCP Server to Caliban as a systemd service.
|
||||||
|
#
|
||||||
|
# The server runs in xmlrpc mode with HTTP transport, exposing the MCP
|
||||||
|
# protocol over streamable-http for consumption by MCP Switchboard on Oberon.
|
||||||
|
#
|
||||||
|
# Pattern: venv + pip install from PyPI (matches Kernos deployment)
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# ansible-playbook freecad_mcp/deploy.yml
|
||||||
|
#
|
||||||
|
# Required host_vars (caliban.incus.yml):
|
||||||
|
# freecad_mcp_user: harper
|
||||||
|
# freecad_mcp_group: harper
|
||||||
|
# freecad_mcp_directory: /srv/freecad-mcp
|
||||||
|
# freecad_mcp_port: 22082
|
||||||
|
# freecad_mcp_version: "0.5.0" # PyPI version to pin
|
||||||
|
#
|
||||||
|
# Optional host_vars:
|
||||||
|
# freecad_mcp_host: "0.0.0.0"
|
||||||
|
# freecad_mcp_log_level: INFO
|
||||||
|
# freecad_mcp_mode: xmlrpc
|
||||||
|
# freecad_mcp_xmlrpc_host: "localhost"
|
||||||
|
# freecad_mcp_xmlrpc_port: 9875
|
||||||
|
# freecad_mcp_timeout_ms: 30000
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
- name: Deploy FreeCAD Robust MCP Server
|
||||||
|
hosts: freecad_mcp
|
||||||
|
vars:
|
||||||
|
ansible_common_remote_group: "{{ freecad_mcp_group }}"
|
||||||
|
allow_world_readable_tmpfiles: true
|
||||||
|
tasks:
|
||||||
|
|
||||||
|
# =========================================================================
|
||||||
|
# User & Directory Setup
|
||||||
|
# =========================================================================
|
||||||
|
|
||||||
|
- name: Create FreeCAD MCP group
|
||||||
|
become: true
|
||||||
|
ansible.builtin.group:
|
||||||
|
name: "{{ freecad_mcp_group }}"
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Create FreeCAD MCP user
|
||||||
|
become: true
|
||||||
|
ansible.builtin.user:
|
||||||
|
name: "{{ freecad_mcp_user }}"
|
||||||
|
group: "{{ freecad_mcp_group }}"
|
||||||
|
home: "/home/{{ freecad_mcp_user }}"
|
||||||
|
shell: /bin/bash
|
||||||
|
system: false
|
||||||
|
create_home: true
|
||||||
|
|
||||||
|
- name: Add keeper_user to FreeCAD MCP group
|
||||||
|
become: true
|
||||||
|
ansible.builtin.user:
|
||||||
|
name: "{{ keeper_user }}"
|
||||||
|
groups: "{{ freecad_mcp_group }}"
|
||||||
|
append: true
|
||||||
|
|
||||||
|
- name: Add principal_user to FreeCAD MCP group
|
||||||
|
become: true
|
||||||
|
ansible.builtin.user:
|
||||||
|
name: "{{ principal_user }}"
|
||||||
|
groups: "{{ freecad_mcp_group }}"
|
||||||
|
append: true
|
||||||
|
|
||||||
|
- name: Add freecad_mcp_user to principal_user's primary group
|
||||||
|
become: true
|
||||||
|
ansible.builtin.user:
|
||||||
|
name: "{{ freecad_mcp_user }}"
|
||||||
|
groups: "{{ principal_user }}"
|
||||||
|
append: true
|
||||||
|
|
||||||
|
- name: Reset connection to pick up new group membership
|
||||||
|
ansible.builtin.meta: reset_connection
|
||||||
|
|
||||||
|
- name: Create application directory
|
||||||
|
become: true
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ freecad_mcp_directory }}"
|
||||||
|
owner: "{{ freecad_mcp_user }}"
|
||||||
|
group: "{{ freecad_mcp_group }}"
|
||||||
|
state: directory
|
||||||
|
mode: '750'
|
||||||
|
|
||||||
|
# =========================================================================
|
||||||
|
# System Dependencies
|
||||||
|
# =========================================================================
|
||||||
|
|
||||||
|
- name: Ensure Python 3, venv, dev headers, and FreeCAD are installed
|
||||||
|
become: true
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name: [python3, python3-venv, python3-dev, freecad]
|
||||||
|
state: present
|
||||||
|
update_cache: true
|
||||||
|
|
||||||
|
# =========================================================================
|
||||||
|
# Virtual Environment & Package Installation
|
||||||
|
# =========================================================================
|
||||||
|
|
||||||
|
- name: Create virtual environment
|
||||||
|
become: true
|
||||||
|
become_user: "{{ freecad_mcp_user }}"
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: "python3 -m venv {{ freecad_mcp_directory }}/.venv/"
|
||||||
|
creates: "{{ freecad_mcp_directory }}/.venv/bin/activate"
|
||||||
|
|
||||||
|
- name: Install wheel in virtual environment
|
||||||
|
become: true
|
||||||
|
become_user: "{{ freecad_mcp_user }}"
|
||||||
|
ansible.builtin.pip:
|
||||||
|
name:
|
||||||
|
- wheel
|
||||||
|
state: latest
|
||||||
|
virtualenv: "{{ freecad_mcp_directory }}/.venv"
|
||||||
|
|
||||||
|
- name: Install freecad-robust-mcp from PyPI
|
||||||
|
become: true
|
||||||
|
become_user: "{{ freecad_mcp_user }}"
|
||||||
|
ansible.builtin.pip:
|
||||||
|
name:
|
||||||
|
- "freecad-robust-mcp=={{ freecad_mcp_version }}"
|
||||||
|
virtualenv: "{{ freecad_mcp_directory }}/.venv"
|
||||||
|
virtualenv_command: python3 -m venv
|
||||||
|
notify: restart freecad-mcp
|
||||||
|
|
||||||
|
# =========================================================================
|
||||||
|
# Configuration
|
||||||
|
# =========================================================================
|
||||||
|
|
||||||
|
- name: Template FreeCAD MCP .env configuration
|
||||||
|
become: true
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: .env.j2
|
||||||
|
dest: "{{ freecad_mcp_directory }}/.env"
|
||||||
|
owner: "{{ freecad_mcp_user }}"
|
||||||
|
group: "{{ freecad_mcp_group }}"
|
||||||
|
mode: '640'
|
||||||
|
notify: restart freecad-mcp
|
||||||
|
|
||||||
|
# =========================================================================
|
||||||
|
# Systemd Service
|
||||||
|
# =========================================================================
|
||||||
|
|
||||||
|
- name: Template systemd service file
|
||||||
|
become: true
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: freecad-mcp.service.j2
|
||||||
|
dest: /etc/systemd/system/freecad-mcp.service
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: '644'
|
||||||
|
notify: restart freecad-mcp
|
||||||
|
|
||||||
|
- name: Enable and start freecad-mcp service
|
||||||
|
become: true
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: freecad-mcp
|
||||||
|
enabled: true
|
||||||
|
state: started
|
||||||
|
daemon_reload: true
|
||||||
|
|
||||||
|
# =========================================================================
|
||||||
|
# Validation
|
||||||
|
# =========================================================================
|
||||||
|
|
||||||
|
- name: Flush handlers to restart service before validation
|
||||||
|
ansible.builtin.meta: flush_handlers
|
||||||
|
|
||||||
|
- name: Wait for FreeCAD MCP server to start
|
||||||
|
ansible.builtin.wait_for:
|
||||||
|
port: "{{ freecad_mcp_port }}"
|
||||||
|
host: localhost
|
||||||
|
delay: 3
|
||||||
|
timeout: 30
|
||||||
|
|
||||||
|
- name: Validate FreeCAD MCP HTTP endpoint is responding
|
||||||
|
ansible.builtin.uri:
|
||||||
|
url: "http://localhost:{{ freecad_mcp_port }}/mcp"
|
||||||
|
method: POST
|
||||||
|
body_format: json
|
||||||
|
body:
|
||||||
|
jsonrpc: "2.0"
|
||||||
|
method: "initialize"
|
||||||
|
id: 1
|
||||||
|
params:
|
||||||
|
protocolVersion: "2025-03-26"
|
||||||
|
capabilities: {}
|
||||||
|
clientInfo:
|
||||||
|
name: "ansible-healthcheck"
|
||||||
|
version: "1.0.0"
|
||||||
|
status_code: [200]
|
||||||
|
return_content: true
|
||||||
|
register: mcp_check
|
||||||
|
retries: 5
|
||||||
|
delay: 5
|
||||||
|
until: mcp_check.status == 200
|
||||||
|
|
||||||
|
- name: Display server info
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: >-
|
||||||
|
FreeCAD MCP Server deployed successfully on
|
||||||
|
caliban.incus:{{ freecad_mcp_port }}
|
||||||
|
|
||||||
|
# =========================================================================
|
||||||
|
# Handlers
|
||||||
|
# =========================================================================
|
||||||
|
|
||||||
|
handlers:
|
||||||
|
- name: restart freecad-mcp
|
||||||
|
become: true
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: freecad-mcp
|
||||||
|
state: restarted
|
||||||
23
ansible/freecad_mcp/freecad-mcp.service.j2
Normal file
23
ansible/freecad_mcp/freecad-mcp.service.j2
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=FreeCAD Robust MCP Server
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User={{ freecad_mcp_user }}
|
||||||
|
Group={{ freecad_mcp_group }}
|
||||||
|
WorkingDirectory={{ freecad_mcp_directory }}
|
||||||
|
ExecStart={{ freecad_mcp_directory }}/.venv/bin/freecad-mcp
|
||||||
|
EnvironmentFile={{ freecad_mcp_directory }}/.env
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=5
|
||||||
|
|
||||||
|
# Security hardening — MCP server needs no special privileges
|
||||||
|
NoNewPrivileges=true
|
||||||
|
ProtectSystem=strict
|
||||||
|
ProtectHome=read-only
|
||||||
|
PrivateTmp=true
|
||||||
|
ReadWritePaths={{ freecad_mcp_directory }}
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
@@ -77,7 +77,7 @@
|
|||||||
- name: Ensure /etc/haproxy/certs directory exists
|
- name: Ensure /etc/haproxy/certs directory exists
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
path: /etc/haproxy/certs
|
path: /etc/haproxy/certs
|
||||||
owner: "{{ certbot_user | default('certbot') }}"
|
owner: "{{ haproxy_user | default('haproxy') }}"
|
||||||
group: "{{ haproxy_group | default('haproxy') }}"
|
group: "{{ haproxy_group | default('haproxy') }}"
|
||||||
state: directory
|
state: directory
|
||||||
mode: '0750'
|
mode: '0750'
|
||||||
|
|||||||
@@ -27,13 +27,14 @@ anythingllm_rel: master
|
|||||||
athena_rel: main
|
athena_rel: main
|
||||||
athena_mcp_rel: main
|
athena_mcp_rel: main
|
||||||
argos_rel: master
|
argos_rel: master
|
||||||
arke_rel: master
|
arke_rel: main
|
||||||
angelia_rel: master
|
angelia_rel: master
|
||||||
kairos_rel: master
|
kairos_rel: master
|
||||||
kairos_mcp_rel: master
|
kairos_mcp_rel: master
|
||||||
spelunker_rel: master
|
spelunker_rel: master
|
||||||
mcp_switchboard_rel: master
|
mcp_switchboard_rel: master
|
||||||
kernos_rel: master
|
kernos_rel: master
|
||||||
|
rommie_rel: master
|
||||||
# PyPI release version (no 'v' prefix) - https://pypi.org/project/open-webui/
|
# PyPI release version (no 'v' prefix) - https://pypi.org/project/open-webui/
|
||||||
openwebui_rel: 0.8.3
|
openwebui_rel: 0.8.3
|
||||||
pulseaudio_module_xrdp_rel:
|
pulseaudio_module_xrdp_rel:
|
||||||
@@ -52,6 +53,7 @@ neo4j_mcp_url: http://circe.helu.ca:22034/mcp
|
|||||||
nike_mcp_url: http://puck.incus:22031/mcp
|
nike_mcp_url: http://puck.incus:22031/mcp
|
||||||
korax_mcp_url: http://korax.helu.ca:22021/mcp
|
korax_mcp_url: http://korax.helu.ca:22021/mcp
|
||||||
rommie_mcp_url: http://caliban.incus:22031/mcp
|
rommie_mcp_url: http://caliban.incus:22031/mcp
|
||||||
|
freecad_mcp_url: http://caliban.incus:22082/mcp
|
||||||
|
|
||||||
# Monitoring and Logging (internal endpoints on Prospero)
|
# Monitoring and Logging (internal endpoints on Prospero)
|
||||||
loki_url: http://prospero.incus:3100/loki/api/v1/push
|
loki_url: http://prospero.incus:3100/loki/api/v1/push
|
||||||
@@ -95,7 +97,7 @@ smtp_from_name: "Ouranos"
|
|||||||
|
|
||||||
# Release directory paths
|
# Release directory paths
|
||||||
github_dir: ~/gh
|
github_dir: ~/gh
|
||||||
repo_dir: ~/dv
|
repo_dir: ~/git
|
||||||
rel_dir: ~/rel
|
rel_dir: ~/rel
|
||||||
|
|
||||||
# Vault Variable Mappings
|
# Vault Variable Mappings
|
||||||
|
|||||||
@@ -6,7 +6,9 @@ services:
|
|||||||
- alloy
|
- alloy
|
||||||
- caliban
|
- caliban
|
||||||
- docker
|
- docker
|
||||||
|
- freecad_mcp
|
||||||
- kernos
|
- kernos
|
||||||
|
- rommie
|
||||||
|
|
||||||
# Account Taxonomy
|
# Account Taxonomy
|
||||||
# principal_user is the AI agent operator account on this host
|
# principal_user is the AI agent operator account on this host
|
||||||
@@ -16,6 +18,27 @@ principal_uid: 1000
|
|||||||
# Alloy
|
# Alloy
|
||||||
alloy_log_level: "warn"
|
alloy_log_level: "warn"
|
||||||
|
|
||||||
|
# Rommie MCP Server Configuration (Agent S GUI Automation)
|
||||||
|
rommie_port: 22031
|
||||||
|
rommie_host: "0.0.0.0"
|
||||||
|
rommie_display: ":10"
|
||||||
|
rommie_allowed_hosts: "caliban.incus"
|
||||||
|
rommie_model: "Qwen3-VL-30B-A3B-Instruct-UD-Q5_K_XL.gguf"
|
||||||
|
rommie_model_url: "http://nyx.helu.ca:22078"
|
||||||
|
rommie_provider: "openai"
|
||||||
|
rommie_ground_provider: "huggingface"
|
||||||
|
rommie_ground_url: "http://pan.helu.ca:22078"
|
||||||
|
rommie_ground_model: "UI-TARS-7B-DPO-Q6_K_L.gguf"
|
||||||
|
rommie_grounding_width: 1024
|
||||||
|
rommie_grounding_height: 1024
|
||||||
|
|
||||||
|
# FreeCAD Robust MCP Server Configuration
|
||||||
|
freecad_mcp_user: harper
|
||||||
|
freecad_mcp_group: harper
|
||||||
|
freecad_mcp_directory: /srv/freecad-mcp
|
||||||
|
freecad_mcp_port: 22082
|
||||||
|
freecad_mcp_version: "0.5.0"
|
||||||
|
|
||||||
# Kernos MCP Shell Server Configuration
|
# Kernos MCP Shell Server Configuration
|
||||||
kernos_user: harper
|
kernos_user: harper
|
||||||
kernos_group: harper
|
kernos_group: harper
|
||||||
|
|||||||
@@ -131,6 +131,11 @@ haproxy_backends:
|
|||||||
backend_port: 22081
|
backend_port: 22081
|
||||||
health_path: "/chat"
|
health_path: "/chat"
|
||||||
|
|
||||||
|
- subdomain: "mnemosyne"
|
||||||
|
backend_host: "puck.incus"
|
||||||
|
backend_port: 23181
|
||||||
|
health_path: "/ready/"
|
||||||
|
|
||||||
- subdomain: "nextcloud"
|
- subdomain: "nextcloud"
|
||||||
backend_host: "rosalind.incus"
|
backend_host: "rosalind.incus"
|
||||||
backend_port: 22083
|
backend_port: 22083
|
||||||
|
|||||||
@@ -32,6 +32,10 @@ casdoor:
|
|||||||
hosts:
|
hosts:
|
||||||
titania.incus:
|
titania.incus:
|
||||||
|
|
||||||
|
freecad_mcp:
|
||||||
|
hosts:
|
||||||
|
caliban.incus:
|
||||||
|
|
||||||
kernos:
|
kernos:
|
||||||
hosts:
|
hosts:
|
||||||
caliban.incus:
|
caliban.incus:
|
||||||
|
|||||||
32
ansible/rommie/.env.j2
Normal file
32
ansible/rommie/.env.j2
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
# Rommie Environment Configuration
|
||||||
|
# MCP server wrapping Agent S for GUI automation
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# Required for Agent S
|
||||||
|
# ============================================================================
|
||||||
|
HF_TOKEN=0000
|
||||||
|
OPENAI_API_KEY=0000
|
||||||
|
DISPLAY={{ rommie_display }}
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# Agent S Model Configuration
|
||||||
|
# ============================================================================
|
||||||
|
ROMMIE_MODEL={{ rommie_model }}
|
||||||
|
ROMMIE_MODEL_URL={{ rommie_model_url }}
|
||||||
|
ROMMIE_PROVIDER={{ rommie_provider | default('openai') }}
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# Grounding Model Configuration
|
||||||
|
# ============================================================================
|
||||||
|
ROMMIE_GROUND_PROVIDER={{ rommie_ground_provider | default('huggingface') }}
|
||||||
|
ROMMIE_GROUND_URL={{ rommie_ground_url }}
|
||||||
|
ROMMIE_GROUND_MODEL={{ rommie_ground_model }}
|
||||||
|
ROMMIE_GROUNDING_WIDTH={{ rommie_grounding_width | default(1024) }}
|
||||||
|
ROMMIE_GROUNDING_HEIGHT={{ rommie_grounding_height | default(1024) }}
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# Server Configuration
|
||||||
|
# ============================================================================
|
||||||
|
ROMMIE_HOST={{ rommie_host | default('0.0.0.0') }}
|
||||||
|
ROMMIE_PORT={{ rommie_port }}
|
||||||
|
ROMMIE_ALLOWED_HOSTS={{ rommie_allowed_hosts }}
|
||||||
82
ansible/rommie/deploy.yml
Normal file
82
ansible/rommie/deploy.yml
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
---
|
||||||
|
- name: Deploy Agent S (Rommie dependency)
|
||||||
|
import_playbook: ../agent_s/deploy.yml
|
||||||
|
|
||||||
|
- name: Deploy Rommie MCP Server
|
||||||
|
hosts: caliban
|
||||||
|
become: yes
|
||||||
|
vars:
|
||||||
|
rommie_venv: "/home/{{principal_user}}/env/rommie"
|
||||||
|
rommie_repo: "/home/{{principal_user}}/rommie"
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Create Rommie application directory
|
||||||
|
become_user: "{{principal_user}}"
|
||||||
|
file:
|
||||||
|
path: "{{rommie_repo}}"
|
||||||
|
state: directory
|
||||||
|
mode: '0755'
|
||||||
|
|
||||||
|
- name: Transfer and extract Rommie
|
||||||
|
become_user: "{{principal_user}}"
|
||||||
|
ansible.builtin.unarchive:
|
||||||
|
src: "~/rel/rommie_{{rommie_rel}}.tar"
|
||||||
|
dest: "{{rommie_repo}}"
|
||||||
|
|
||||||
|
- name: Create Rommie virtual environment
|
||||||
|
become_user: "{{principal_user}}"
|
||||||
|
command: python3 -m venv --system-site-packages {{rommie_venv}}
|
||||||
|
args:
|
||||||
|
creates: "{{rommie_venv}}/bin/activate"
|
||||||
|
|
||||||
|
- name: Install Rommie into virtual environment
|
||||||
|
become_user: "{{principal_user}}"
|
||||||
|
pip:
|
||||||
|
name: "{{rommie_repo}}"
|
||||||
|
extra_args: "-e"
|
||||||
|
virtualenv: "{{rommie_venv}}"
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Deploy Rommie environment file
|
||||||
|
become_user: "{{principal_user}}"
|
||||||
|
template:
|
||||||
|
src: .env.j2
|
||||||
|
dest: "{{rommie_repo}}/.env"
|
||||||
|
mode: '0600'
|
||||||
|
|
||||||
|
- name: Deploy Rommie systemd service
|
||||||
|
template:
|
||||||
|
src: rommie.service.j2
|
||||||
|
dest: /etc/systemd/system/rommie.service
|
||||||
|
mode: '0644'
|
||||||
|
notify:
|
||||||
|
- Reload systemd
|
||||||
|
- Restart rommie
|
||||||
|
|
||||||
|
- name: Enable and start Rommie service
|
||||||
|
systemd:
|
||||||
|
name: rommie
|
||||||
|
enabled: yes
|
||||||
|
state: started
|
||||||
|
daemon_reload: yes
|
||||||
|
|
||||||
|
- name: Verify Rommie MCP endpoint is reachable
|
||||||
|
ansible.builtin.uri:
|
||||||
|
url: "http://localhost:{{rommie_port}}/mcp"
|
||||||
|
method: GET
|
||||||
|
status_code: [200, 405]
|
||||||
|
timeout: 15
|
||||||
|
register: rommie_health
|
||||||
|
retries: 5
|
||||||
|
delay: 3
|
||||||
|
until: rommie_health.status in [200, 405]
|
||||||
|
|
||||||
|
handlers:
|
||||||
|
- name: Reload systemd
|
||||||
|
systemd:
|
||||||
|
daemon_reload: yes
|
||||||
|
|
||||||
|
- name: Restart rommie
|
||||||
|
systemd:
|
||||||
|
name: rommie
|
||||||
|
state: restarted
|
||||||
18
ansible/rommie/rommie.service.j2
Normal file
18
ansible/rommie/rommie.service.j2
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Rommie MCP Server (Agent S GUI Automation)
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User={{ principal_user }}
|
||||||
|
WorkingDirectory=/home/{{ principal_user }}/rommie
|
||||||
|
EnvironmentFile=/home/{{ principal_user }}/rommie/.env
|
||||||
|
ExecStart=/home/{{ principal_user }}/env/rommie/bin/rommie
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=10
|
||||||
|
StandardOutput=journal
|
||||||
|
StandardError=journal
|
||||||
|
SyslogIdentifier=rommie
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
@@ -106,6 +106,8 @@ Autonomous computer agent learning through environmental interaction.
|
|||||||
- Docker engine
|
- Docker engine
|
||||||
- Agent S MCP Server (MATE desktop, AT-SPI automation)
|
- Agent S MCP Server (MATE desktop, AT-SPI automation)
|
||||||
- Kernos MCP Shell Server (port 22021)
|
- Kernos MCP Shell Server (port 22021)
|
||||||
|
- Rommie MCP Server (port 22031) — agent-to-agent GUI automation via Agent S
|
||||||
|
- FreeCAD Robust MCP Server (port 22082) — CAD automation via FreeCAD XML-RPC
|
||||||
- GPU passthrough for vision tasks
|
- GPU passthrough for vision tasks
|
||||||
- RDP access (port 25521)
|
- RDP access (port 25521)
|
||||||
|
|
||||||
@@ -280,7 +282,9 @@ Services with standalone deploy playbooks (not in `site.yml`):
|
|||||||
| `jupyterlab/deploy.yml` | Puck | JupyterLab + OAuth2-Proxy |
|
| `jupyterlab/deploy.yml` | Puck | JupyterLab + OAuth2-Proxy |
|
||||||
| `kernos/deploy.yml` | Caliban | Kernos MCP shell server |
|
| `kernos/deploy.yml` | Caliban | Kernos MCP shell server |
|
||||||
| `lobechat/deploy.yml` | Rosalind | LobeChat AI chat |
|
| `lobechat/deploy.yml` | Rosalind | LobeChat AI chat |
|
||||||
|
| `rommie/deploy.yml` | Caliban | Rommie MCP server (Agent S GUI automation) |
|
||||||
| `neo4j_mcp/deploy.yml` | Miranda | Neo4j MCP Server |
|
| `neo4j_mcp/deploy.yml` | Miranda | Neo4j MCP Server |
|
||||||
|
| `freecad_mcp/deploy.yml` | Caliban | FreeCAD Robust MCP Server |
|
||||||
| `rabbitmq/deploy.yml` | Oberon | RabbitMQ message queue |
|
| `rabbitmq/deploy.yml` | Oberon | RabbitMQ message queue |
|
||||||
|
|
||||||
### Lifecycle Playbooks
|
### Lifecycle Playbooks
|
||||||
|
|||||||
Reference in New Issue
Block a user