feat(connectors): connector hub — registry + mirrors, devops/cloud/iot categories, 15 service entries (forgejo live, github, aws, localstack, minio, gcloud, azure, azurite, cloudflare, vercel, k8s, terraform, ansible, aws-iot, mqtt)
This commit is contained in:
parent
141def0fc7
commit
912cf45b51
2 changed files with 386 additions and 0 deletions
284
.aurelio/connectors/registry.yaml
Normal file
284
.aurelio/connectors/registry.yaml
Normal file
|
|
@ -0,0 +1,284 @@
|
||||||
|
# Aurélio Connector Hub — single source of truth
|
||||||
|
#
|
||||||
|
# ONE place external integrations are declared. All surfaces derive from it via
|
||||||
|
# scripts/generate-connector-mirrors.py:
|
||||||
|
#
|
||||||
|
# * .aurelio/connectors/dist/mcp.connectors.json -> MCP fleet / model router
|
||||||
|
# * .aurelio/connectors/dist/theia.connectors.json -> @aurelio/mcp Connections view
|
||||||
|
#
|
||||||
|
# Schema per entry:
|
||||||
|
# id stable machine id
|
||||||
|
# label human label (UI)
|
||||||
|
# category saas | cad | daw | edm | devops | cloud | iot | other
|
||||||
|
# kind mcp | oauth | api-key | sidecar
|
||||||
|
# mcp -> remote MCP server (existing *.portugalfuturista.org fleet)
|
||||||
|
# oauth -> SaaS OAuth2 (authorization-code) — needs a tenant/client id
|
||||||
|
# api-key -> SaaS token
|
||||||
|
# sidecar -> local native-host bridge (COM / Remote Script / OSC)
|
||||||
|
# auth none | oauth2 | api_key | sidecar
|
||||||
|
# endpoint remote base url (kind=mcp) or api root (oauth/api-key); null for sidecar
|
||||||
|
# surfaces which downstreams get this connector: mcp | theia | portal
|
||||||
|
# status declared | provisioned | live
|
||||||
|
# declared -> catalogued only; no secrets/host wired yet
|
||||||
|
# provisioned -> secrets present / sidecar built; not exercised
|
||||||
|
# live -> verified end-to-end against the real host
|
||||||
|
# scopes OAuth scopes (auth=oauth2) — documentation until provisioned
|
||||||
|
# host sidecar host platform (kind=sidecar): windows | macos | any
|
||||||
|
# notes provenance / caveats
|
||||||
|
#
|
||||||
|
# Regenerate mirrors after editing:
|
||||||
|
# python3 scripts/generate-connector-mirrors.py --write-in-place
|
||||||
|
# python3 scripts/generate-connector-mirrors.py --check # CI guard
|
||||||
|
#
|
||||||
|
# NOTE: `status: declared` is the honest default — real OAuth tenants, MCP
|
||||||
|
# servers, and native sidecars are per-connector follow-ups, NOT implied by
|
||||||
|
# listing here. Declaring a connector is the catalog step, not the integration.
|
||||||
|
|
||||||
|
version: 1
|
||||||
|
|
||||||
|
connectors:
|
||||||
|
# ── DevOps (forges / IaC / k8s) ───────────────────────────────────────────
|
||||||
|
- id: forgejo
|
||||||
|
label: Forgejo (self-hosted git + actions)
|
||||||
|
category: devops
|
||||||
|
kind: api-key
|
||||||
|
auth: api_key
|
||||||
|
endpoint: https://code.portugalfuturista.org
|
||||||
|
surfaces: [mcp, theia, portal]
|
||||||
|
status: live
|
||||||
|
scopes: []
|
||||||
|
host: null
|
||||||
|
notes: DEFAULT forge (self-hosted first policy). LAN origin 192.168.0.9:3001. CLI = tea. Tokens in Vaultwarden.
|
||||||
|
|
||||||
|
- id: github
|
||||||
|
label: GitHub
|
||||||
|
category: devops
|
||||||
|
kind: api-key
|
||||||
|
auth: api_key
|
||||||
|
endpoint: https://api.github.com
|
||||||
|
surfaces: [mcp, theia]
|
||||||
|
status: declared
|
||||||
|
scopes: []
|
||||||
|
host: null
|
||||||
|
notes: Only for public mirrors/upstreams — Forgejo is the default forge. CLI = gh.
|
||||||
|
|
||||||
|
- id: kubernetes
|
||||||
|
label: Kubernetes
|
||||||
|
category: devops
|
||||||
|
kind: sidecar
|
||||||
|
auth: sidecar
|
||||||
|
endpoint: null
|
||||||
|
surfaces: [theia]
|
||||||
|
status: declared
|
||||||
|
scopes: []
|
||||||
|
host: any
|
||||||
|
notes: CLI-driven (kubectl/helm). k3s on Proxmox is the self-hosted target; kubeconfig per cluster.
|
||||||
|
|
||||||
|
- id: terraform
|
||||||
|
label: Terraform / OpenTofu
|
||||||
|
category: devops
|
||||||
|
kind: sidecar
|
||||||
|
auth: sidecar
|
||||||
|
endpoint: null
|
||||||
|
surfaces: [theia]
|
||||||
|
status: declared
|
||||||
|
scopes: []
|
||||||
|
host: any
|
||||||
|
notes: "CLI-driven IaC. Prefer OpenTofu (license). State backend: MinIO S3 (self-hosted)."
|
||||||
|
|
||||||
|
- id: ansible
|
||||||
|
label: Ansible
|
||||||
|
category: devops
|
||||||
|
kind: sidecar
|
||||||
|
auth: sidecar
|
||||||
|
endpoint: null
|
||||||
|
surfaces: [theia]
|
||||||
|
status: declared
|
||||||
|
scopes: []
|
||||||
|
host: any
|
||||||
|
notes: CLI-driven config management for the Proxmox fleet (asus/gigabyte/lattepanda).
|
||||||
|
|
||||||
|
# ── Cloud (public + self-hosted emulators) ────────────────────────────────
|
||||||
|
- id: aws
|
||||||
|
label: AWS
|
||||||
|
category: cloud
|
||||||
|
kind: api-key
|
||||||
|
auth: api_key
|
||||||
|
endpoint: https://aws.amazon.com
|
||||||
|
surfaces: [mcp, theia]
|
||||||
|
status: declared
|
||||||
|
scopes: []
|
||||||
|
host: null
|
||||||
|
notes: Production AWS only when explicitly required. Dev = aws-localstack/minio endpoints. CLI = aws.
|
||||||
|
|
||||||
|
- id: aws-localstack
|
||||||
|
label: LocalStack (AWS emulator)
|
||||||
|
category: cloud
|
||||||
|
kind: api-key
|
||||||
|
auth: api_key
|
||||||
|
endpoint: http://192.168.0.40:4566
|
||||||
|
surfaces: [mcp, theia]
|
||||||
|
status: declared
|
||||||
|
scopes: []
|
||||||
|
host: null
|
||||||
|
notes: Self-hosted AWS emulation on lattepanda. CLI = aws --endpoint-url or awslocal.
|
||||||
|
|
||||||
|
- id: minio
|
||||||
|
label: MinIO (S3-compatible, self-hosted)
|
||||||
|
category: cloud
|
||||||
|
kind: api-key
|
||||||
|
auth: api_key
|
||||||
|
endpoint: http://192.168.0.40:9000
|
||||||
|
surfaces: [mcp, theia, portal]
|
||||||
|
status: declared
|
||||||
|
scopes: []
|
||||||
|
host: null
|
||||||
|
notes: Self-hosted S3 on lattepanda (console :9001). Default object store + Terraform state backend.
|
||||||
|
|
||||||
|
- id: google-cloud
|
||||||
|
label: Google Cloud
|
||||||
|
category: cloud
|
||||||
|
kind: oauth
|
||||||
|
auth: oauth2
|
||||||
|
endpoint: https://cloudresourcemanager.googleapis.com
|
||||||
|
surfaces: [mcp, theia]
|
||||||
|
status: declared
|
||||||
|
scopes: [cloud-platform]
|
||||||
|
host: null
|
||||||
|
notes: CLI = gcloud. No real self-hosted equivalent; firebase emulators / fake-gcs-server for dev.
|
||||||
|
|
||||||
|
- id: azure
|
||||||
|
label: Microsoft Azure
|
||||||
|
category: cloud
|
||||||
|
kind: oauth
|
||||||
|
auth: oauth2
|
||||||
|
endpoint: https://management.azure.com
|
||||||
|
surfaces: [mcp, theia]
|
||||||
|
status: declared
|
||||||
|
scopes: [user_impersonation]
|
||||||
|
host: null
|
||||||
|
notes: CLI = az. Dev storage = azure-azurite.
|
||||||
|
|
||||||
|
- id: azure-azurite
|
||||||
|
label: Azurite (Azure Storage emulator)
|
||||||
|
category: cloud
|
||||||
|
kind: api-key
|
||||||
|
auth: api_key
|
||||||
|
endpoint: http://192.168.0.40:10000
|
||||||
|
surfaces: [mcp, theia]
|
||||||
|
status: declared
|
||||||
|
scopes: []
|
||||||
|
host: null
|
||||||
|
notes: Self-hosted Azure Storage emulation on lattepanda (blob :10000, queue :10001, table :10002).
|
||||||
|
|
||||||
|
- id: cloudflare
|
||||||
|
label: Cloudflare
|
||||||
|
category: cloud
|
||||||
|
kind: api-key
|
||||||
|
auth: api_key
|
||||||
|
endpoint: https://api.cloudflare.com/client/v4
|
||||||
|
surfaces: [mcp, theia]
|
||||||
|
status: declared
|
||||||
|
scopes: []
|
||||||
|
host: null
|
||||||
|
notes: Tunnel pf-tunnel-v2 on asus terminates *.portugalfuturista.org. CLIs = cloudflared, wrangler.
|
||||||
|
|
||||||
|
- id: vercel
|
||||||
|
label: Vercel
|
||||||
|
category: cloud
|
||||||
|
kind: api-key
|
||||||
|
auth: api_key
|
||||||
|
endpoint: https://api.vercel.com
|
||||||
|
surfaces: [mcp, theia]
|
||||||
|
status: declared
|
||||||
|
scopes: []
|
||||||
|
host: null
|
||||||
|
notes: CLI = vercel. Edge deploys only when Forgejo Pages/static hosting is not enough.
|
||||||
|
|
||||||
|
# ── IoT ───────────────────────────────────────────────────────────────────
|
||||||
|
- id: aws-iot
|
||||||
|
label: AWS IoT Core
|
||||||
|
category: iot
|
||||||
|
kind: api-key
|
||||||
|
auth: api_key
|
||||||
|
endpoint: https://iot.amazonaws.com
|
||||||
|
surfaces: [mcp, theia]
|
||||||
|
status: declared
|
||||||
|
scopes: []
|
||||||
|
host: null
|
||||||
|
notes: Device registry/shadows for savearth firmware. Uses aws connector credentials. CLIs = aws iot, mosquitto-clients.
|
||||||
|
|
||||||
|
- id: mqtt-local
|
||||||
|
label: MQTT (self-hosted broker)
|
||||||
|
category: iot
|
||||||
|
kind: api-key
|
||||||
|
auth: api_key
|
||||||
|
endpoint: null
|
||||||
|
surfaces: [mcp, theia]
|
||||||
|
status: declared
|
||||||
|
scopes: []
|
||||||
|
host: null
|
||||||
|
notes: Self-hosted mosquitto/EMQX broker — endpoint TBD when deployed. CLIs = mosquitto_pub/sub.
|
||||||
|
|
||||||
|
# ── SaaS (Office / Atlassian) ─────────────────────────────────────────────
|
||||||
|
- id: microsoft-graph
|
||||||
|
label: Microsoft 365 (Graph)
|
||||||
|
category: saas
|
||||||
|
kind: oauth
|
||||||
|
auth: oauth2
|
||||||
|
endpoint: https://graph.microsoft.com/v1.0
|
||||||
|
surfaces: [mcp, theia]
|
||||||
|
status: declared
|
||||||
|
scopes: [User.Read, Mail.Read, Calendars.Read, Files.Read, offline_access]
|
||||||
|
host: null
|
||||||
|
notes: Entra ID app registration required; exposes Outlook/OneDrive/Calendar/Teams via Graph.
|
||||||
|
|
||||||
|
- id: atlassian
|
||||||
|
label: Atlassian (Jira + Confluence)
|
||||||
|
category: saas
|
||||||
|
kind: oauth
|
||||||
|
auth: oauth2
|
||||||
|
endpoint: https://api.atlassian.com
|
||||||
|
surfaces: [mcp, theia]
|
||||||
|
status: declared
|
||||||
|
scopes: [read:jira-work, write:jira-work, read:confluence-content.all, offline_access]
|
||||||
|
host: null
|
||||||
|
notes: Atlassian OAuth 2.0 (3LO) app; Jira REST v3 + Confluence REST v2.
|
||||||
|
|
||||||
|
# ── Creative / CAD hosts (sidecar bridges, NOT VSIXs) ─────────────────────
|
||||||
|
- id: solidworks
|
||||||
|
label: SolidWorks
|
||||||
|
category: cad
|
||||||
|
kind: sidecar
|
||||||
|
auth: sidecar
|
||||||
|
endpoint: null
|
||||||
|
surfaces: [theia]
|
||||||
|
status: declared
|
||||||
|
scopes: []
|
||||||
|
host: windows
|
||||||
|
notes: Windows-only. Bridge = COM/ISldWorks automation agent (or VBA add-in) -> MCP over loopback. Surfaces part/assembly/drawing ops.
|
||||||
|
|
||||||
|
- id: ableton-live
|
||||||
|
label: Ableton Live
|
||||||
|
category: daw
|
||||||
|
kind: sidecar
|
||||||
|
auth: sidecar
|
||||||
|
endpoint: null
|
||||||
|
surfaces: [theia]
|
||||||
|
status: declared
|
||||||
|
scopes: []
|
||||||
|
host: any
|
||||||
|
notes: Bridge = Ableton Remote Script (Control Surface) or Max-for-Live device -> OSC/MCP. Surfaces transport/track/clip/scene ops.
|
||||||
|
|
||||||
|
# ── Reference: an already-live MCP connector (documents the `live` shape) ──
|
||||||
|
- id: knowledge-mcp
|
||||||
|
label: Knowledge MCP
|
||||||
|
category: other
|
||||||
|
kind: mcp
|
||||||
|
auth: none
|
||||||
|
endpoint: https://knowledge-mcp.portugalfuturista.org/sse
|
||||||
|
surfaces: [mcp, theia]
|
||||||
|
status: live
|
||||||
|
scopes: []
|
||||||
|
host: null
|
||||||
|
notes: Existing fleet member in .aurelio/mcp_config.json — listed as the reference `live` connector shape.
|
||||||
102
scripts/generate-connector-mirrors.py
Normal file
102
scripts/generate-connector-mirrors.py
Normal file
|
|
@ -0,0 +1,102 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Generate downstream connector-hub mirrors from the single source of truth:
|
||||||
|
|
||||||
|
.aurelio/connectors/registry.yaml
|
||||||
|
|
||||||
|
Outputs (under .aurelio/connectors/dist/ unless --write-in-place is given,
|
||||||
|
which writes the same files — dist/ IS the in-place location here):
|
||||||
|
|
||||||
|
* mcp.connectors.json — machine-readable catalog the MCP fleet / router
|
||||||
|
can load (kind=mcp entries map onto mcp_config.json).
|
||||||
|
* theia.connectors.json — slim shape the @aurelio/mcp Connections view reads:
|
||||||
|
[{id,label,category,kind,auth,status,host,endpoint}].
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
python3 scripts/generate-connector-mirrors.py --write-in-place
|
||||||
|
python3 scripts/generate-connector-mirrors.py --check # exit 1 if dist stale
|
||||||
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
try:
|
||||||
|
import yaml # PyYAML
|
||||||
|
except ImportError: # pragma: no cover
|
||||||
|
print("PyYAML required: pip install pyyaml", file=sys.stderr)
|
||||||
|
sys.exit(2)
|
||||||
|
|
||||||
|
REPLICA_ROOT = Path(__file__).resolve().parent.parent
|
||||||
|
REGISTRY = REPLICA_ROOT / ".aurelio" / "connectors" / "registry.yaml"
|
||||||
|
DIST_DIR = REPLICA_ROOT / ".aurelio" / "connectors" / "dist"
|
||||||
|
|
||||||
|
THEIA_FIELDS = ("id", "label", "category", "kind", "auth", "status", "host", "endpoint", "surfaces")
|
||||||
|
|
||||||
|
|
||||||
|
def load() -> dict:
|
||||||
|
with REGISTRY.open("r", encoding="utf-8") as f:
|
||||||
|
return yaml.safe_load(f)
|
||||||
|
|
||||||
|
|
||||||
|
def emit_theia(data: dict) -> dict:
|
||||||
|
conns = [
|
||||||
|
{k: c.get(k) for k in THEIA_FIELDS}
|
||||||
|
for c in data["connectors"]
|
||||||
|
if "theia" in c.get("surfaces", [])
|
||||||
|
]
|
||||||
|
return {"version": data.get("version", 1), "connectors": conns}
|
||||||
|
|
||||||
|
|
||||||
|
def emit_mcp(data: dict) -> dict:
|
||||||
|
conns = [
|
||||||
|
c for c in data["connectors"]
|
||||||
|
if "mcp" in c.get("surfaces", [])
|
||||||
|
]
|
||||||
|
return {"version": data.get("version", 1), "connectors": conns}
|
||||||
|
|
||||||
|
|
||||||
|
def mirrors() -> dict[str, dict]:
|
||||||
|
data = load()
|
||||||
|
return {
|
||||||
|
"theia.connectors.json": emit_theia(data),
|
||||||
|
"mcp.connectors.json": emit_mcp(data),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def write_in_place() -> None:
|
||||||
|
DIST_DIR.mkdir(parents=True, exist_ok=True)
|
||||||
|
for name, obj in mirrors().items():
|
||||||
|
(DIST_DIR / name).write_text(json.dumps(obj, indent=2) + "\n", encoding="utf-8")
|
||||||
|
print(f"wrote {DIST_DIR / name}")
|
||||||
|
|
||||||
|
|
||||||
|
def check() -> int:
|
||||||
|
stale = []
|
||||||
|
for name, obj in mirrors().items():
|
||||||
|
p = DIST_DIR / name
|
||||||
|
want = json.dumps(obj, indent=2) + "\n"
|
||||||
|
if not p.exists() or p.read_text(encoding="utf-8") != want:
|
||||||
|
stale.append(name)
|
||||||
|
if stale:
|
||||||
|
print("stale connector mirrors (run --write-in-place):", ", ".join(stale), file=sys.stderr)
|
||||||
|
return 1
|
||||||
|
print("connector mirrors up to date")
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
ap = argparse.ArgumentParser(description=__doc__)
|
||||||
|
ap.add_argument("--write-in-place", action="store_true")
|
||||||
|
ap.add_argument("--check", action="store_true")
|
||||||
|
args = ap.parse_args()
|
||||||
|
if args.check:
|
||||||
|
return check()
|
||||||
|
write_in_place()
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
raise SystemExit(main())
|
||||||
Loading…
Reference in a new issue