Skip to content

Feature: unified /api/import + import_model MCP tool (URL fetch) + iris import CLI (ADR-220) #240

@cgbarlow

Description

@cgbarlow

Summary

Give the import surface full Protocol §14 MCP + CLI parity and a single
content-sniffing entry point. Backlogged from the native Sparx XMI work
(ADR-219, shipped in v6.32.0, website-only).

Full plan: docs/plans/adr-220-unified-import-mcp-cli.md (also on branch sparxea-xml-file-format until that PR merges).

The gap

  • The Iris MCP has no import tool (56 tools, none for importing model files) and the CLI has no import command. The MCP is a remote Streamable-HTTP server (iris-mcp.onrender.com, ADR-134) that cannot see the user's local files, so AI agents/scripts can't import models the way the website can.
  • Format dispatch is duplicated (frontend extension/content sniff + five per-format endpoints) — no single source of truth.

Locked decisions (made during ADR-219 planning)

  • File delivery = URL fetch. import_model(source_url, set_id?) — the backend downloads and imports. Only mechanism that works for the remote MCP across all formats incl. multi-MB binaries (.qea/.eap/.pptx); inline base64 can't carry those.
  • Unified endpoint + CLI. Add a content-sniffing POST /api/import dispatcher used by the frontend, the MCP tool, and a new iris import command.

Scope / deliverables

  • ADR-220 + SPEC-220-A (SSRF threat model is the core of the ADR)
  • backend/app/imports/: detect.py (5-format sniff), download.py (SSRF-hardened URL fetch), router.py (POST /api/import, file XOR source_url) — per-format routers delegate to a shared dispatch core (DRY)
  • iris-client.import_model + MCP import_model tool + server_instructions note
  • iris import <file|--url> CLI command
  • Frontend: post everything to /api/import (drop the v6.32.0 client-side sniff)
  • Tests: detect, router, SSRF rejection, client, MCP, CLI, frontend
  • README + CHANGELOG + version bump + GitHub release

Security note

The server-side URL download is an SSRF vector. The plan enforces: https-only scheme allowlist; resolve+block private/loopback/link-local/metadata IPs; pin the vetted IP (DNS-rebinding TOCTOU); no redirects; streaming size cap; timeout; post-download format sniff (reject arbitrary bytes). Requires a /security-review pass on download.py.

Notes

  • No DB migration (writes via existing create_* services; SQLite+Supabase parity).
  • scripts/check_surface_parity.py stays green (it scans only the five known entity routers); MCP + CLI added voluntarily for §14 spirit.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions