Sandbox
@ivnvxd/mcp-server-odoo

MCP server for Odoo ERP access

This server connects an agent to Odoo through MCP so it can search records, read fields, create entries, update data, delete records, and run safe business actions. It also exposes resources, session context, aggregation, and attachment access, with access controls and a YOLO mode for testing.

383 starsβ€’175 forksβ€’Pythonβ€’Updated 11d ago
Who it's for

Builders who want their agent to work with Odoo data and workflows.

What it delivers

You can ask your agent to inspect and change Odoo data instead of switching into the ERP UI.

What it does

Record search and retrieval

Searches Odoo models with domains, fetches individual records, and returns smart field selections by default.

Create, update, and delete tools

Adds CRUD tools with field validation, permission checks, and model-level access control.

Server-side aggregation

Groups, sums, and counts records in Odoo without pulling raw rows back to the client.

Chatter and workflow actions

Posts messages to `mail.thread` records and, in YOLO mode, can call public business methods for workflows like confirm or post.

Resources and attachments

Reads binary fields and `ir.attachment` files through MCP resource URIs, with size limits and safety checks.

Session and model context

Exposes current user, company, timezone, and model field metadata so the agent can answer in the right context.

How to get it

  1. 1The MCP server runs on your local computer (where Claude Desktop is installed), not on…
    curl -LsSf https://astral.sh/uv/install.sh | sh
  2. 2Run
    powershell -c "irm https://astral.sh/uv/install.ps1 | iex"
  3. 3Or use the CLI
    claude mcp add odoo \
      --env ODOO_URL=https://your-odoo-instance.com \
      --env ODOO_API_KEY=your-api-key-here \
      --env ODOO_DB=your-database-name \
      -- uvx mcp-server-odoo
  4. 4For HTTP transport
    docker run --rm -p 8000:8000 \
      -e ODOO_URL=http://host.docker.internal:8069 \
      -e ODOO_API_KEY=your-api-key-here \
      ivnvxd/mcp-server-odoo --transport streamable-http --host 0.0.0.0
  5. 5The image is also available on GHCR: ghcr.io/ivnvxd/mcp-server-odoo
    # Install globally
    pip install mcp-server-odoo
    
    # Or use pipx for isolated environment
    pipx install mcp-server-odoo
  6. 6Then use mcp-server-odoo as the command in your MCP configuration.
    git clone https://github.com/ivnvxd/mcp-server-odoo.git
    cd mcp-server-odoo
    pip install -e .

README

MCP Server for Odoo

CI codecov Ruff Checked with ty Python 3.10+ License: MPL 2.0

An MCP server that enables AI assistants like Claude to interact with Odoo ERP systems. Access business data, search records, create new entries, update existing data, and manage your Odoo instance through natural language.

Works with any Odoo instance! Use YOLO mode for quick testing and demos with any standard Odoo installation. For enterprise security, access controls, and production use, install the Odoo MCP module.

Features

  • πŸ” Search and retrieve any Odoo record (customers, products, invoices, etc.)
  • ✨ Create new records with field validation and permission checks
  • ✏️ Update existing data with smart field handling
  • πŸ—‘οΈ Delete records respecting model-level permissions
  • πŸ”’ Count records matching specific criteria
  • πŸ“‹ Inspect model fields to understand data structure
  • πŸ“Š Server-side aggregation β€” group, sum, and count without pulling raw rows
  • ⚑ Workflow actions β€” invoke public business methods (post invoice, confirm SO, etc.) via an opt-in escape hatch
  • πŸ“Ž Binary & attachment resources β€” fetch images, documents, and ir.attachment files via resource URIs
  • πŸ‘€ Personalized session context β€” the connected user, timezone, and company scope injected into the session instructions
  • πŸ” Secure access with API key or username/password authentication
  • 🎯 Smart pagination for large datasets
  • 🧠 Smart field selection β€” automatically picks the most relevant fields per model
  • πŸ’¬ LLM-optimized output with hierarchical text formatting
  • 🌍 Multi-language support β€” get responses in your preferred language
  • πŸš€ YOLO Mode for quick access with any Odoo instance (no module required)

Installation

Prerequisites

  • Python 3.10 or higher
  • Access to an Odoo instance:
    • Standard mode (production): Version 16.0+ with the Odoo MCP module installed
    • YOLO mode (testing/demos): Any Odoo version with XML-RPC enabled (no module required)

Install UV First

The MCP server runs on your local computer (where Claude Desktop is installed), not on your Odoo server. You need to install UV on your local machine:

macOS/Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
Windows
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"

After installation, restart your terminal to ensure UV is in your PATH.

Installing via MCP Settings (Recommended)

Add this configuration to your MCP settings:

{
  "mcpServers": {
    "odoo": {
      "command": "uvx",
      "args": ["mcp-server-odoo"],
      "env": {
        "ODOO_URL": "https://your-odoo-instance.com",
        "ODOO_API_KEY": "your-api-key-here"
      }
    }
  }
}
Claude Desktop

Add to ~/Library/Application Support/Claude/claude_desktop_config.json:

{
  "mcpServers": {
    "odoo": {
      "command": "uvx",
      "args": ["mcp-server-odoo"],
      "env": {
        "ODOO_URL": "https://your-odoo-instance.com",
        "ODOO_API_KEY": "your-api-key-here",
        "ODOO_DB": "your-database-name"
      }
    }
  }
}
Claude Code

Add to .mcp.json in your project root:

{
  "mcpServers": {
    "odoo": {
      "command": "uvx",
      "args": ["mcp-server-odoo"],
      "env": {
        "ODOO_URL": "https://your-odoo-instance.com",
        "ODOO_API_KEY": "your-api-key-here",
        "ODOO_DB": "your-database-name"
      }
    }
  }
}

Or use the CLI:

claude mcp add odoo \
  --env ODOO_URL=https://your-odoo-instance.com \
  --env ODOO_API_KEY=your-api-key-here \
  --env ODOO_DB=your-database-name \
  -- uvx mcp-server-odoo
Cursor

Add to ~/.cursor/mcp.json:

{
  "mcpServers": {
    "odoo": {
      "command": "uvx",
      "args": ["mcp-server-odoo"],
      "env": {
        "ODOO_URL": "https://your-odoo-instance.com",
        "ODOO_API_KEY": "your-api-key-here",
        "ODOO_DB": "your-database-name"
      }
    }
  }
}
VS Code (with GitHub Copilot)

Add to .vscode/mcp.json in your workspace:

{
  "servers": {
    "odoo": {
      "type": "stdio",
      "command": "uvx",
      "args": ["mcp-server-odoo"],
      "env": {
        "ODOO_URL": "https://your-odoo-instance.com",
        "ODOO_API_KEY": "your-api-key-here",
        "ODOO_DB": "your-database-name"
      }
    }
  }
}

Note: VS Code uses "servers" as the root key, not "mcpServers".

Windsurf

Add to ~/.codeium/windsurf/mcp_config.json:

{
  "mcpServers": {
    "odoo": {
      "command": "uvx",
      "args": ["mcp-server-odoo"],
      "env": {
        "ODOO_URL": "https://your-odoo-instance.com",
        "ODOO_API_KEY": "your-api-key-here",
        "ODOO_DB": "your-database-name"
      }
    }
  }
}
Zed

Add to ~/.config/zed/settings.json:

{
  "context_servers": {
    "odoo": {
      "command": {
        "path": "uvx",
        "args": ["mcp-server-odoo"],
        "env": {
          "ODOO_URL": "https://your-odoo-instance.com",
          "ODOO_API_KEY": "your-api-key-here",
          "ODOO_DB": "your-database-name"
        }
      }
    }
  }
}

Alternative Installation Methods

Using Docker

Run with Docker β€” no Python installation required:

{
  "mcpServers": {
    "odoo": {
      "command": "docker",
      "args": [
        "run", "-i", "--rm",
        "-e", "ODOO_URL=http://host.docker.internal:8069",
        "-e", "ODOO_API_KEY=your-api-key-here",
        "ivnvxd/mcp-server-odoo"
      ]
    }
  }
}

Note: Use host.docker.internal instead of localhost to connect to Odoo running on the host machine.

For HTTP transport:

docker run --rm -p 8000:8000 \
  -e ODOO_URL=http://host.docker.internal:8069 \
  -e ODOO_API_KEY=your-api-key-here \
  ivnvxd/mcp-server-odoo --transport streamable-http --host 0.0.0.0

⚠️ Security: the HTTP transport has no built-in authentication β€” anyone who can reach the port gets Odoo access through the server's credentials. Publish the port only on trusted networks, or front it with an authenticating reverse proxy. See Transport Options.

The image is also available on GHCR: ghcr.io/ivnvxd/mcp-server-odoo

Using pip
# Install globally
pip install mcp-server-odoo

# Or use pipx for isolated environment
pipx install mcp-server-odoo

Then use mcp-server-odoo as the command in your MCP configuration.

From source
git clone https://github.com/ivnvxd/mcp-server-odoo.git
cd mcp-server-odoo
pip install -e .

Then use the full path to the package in your MCP configuration.

Configuration

Environment Variables

The server requires the following environment variables:

VariableRequiredDescriptionExample
ODOO_URLYesYour Odoo instance URLhttps://mycompany.odoo.com
ODOO_API_KEYYes*API key for authentication0ef5b399e9ee9c11b053dfb6eeba8de473c29fcd
ODOO_USERYes*Username (if not using API key)admin
ODOO_PASSWORDYes*Password (if not using API key)admin
ODOO_DBNoDatabase name (auto-detected if not set)mycompany
ODOO_LOCALENoLanguage/locale for Odoo responseses_ES, fr_FR, de_DE
ODOO_YOLONoYOLO mode - bypasses MCP security (⚠️ DEV ONLY)off, read, true
ODOO_MCP_ENABLE_METHOD_CALLSNoEnable the call_model_method tool β€” requires ODOO_YOLO=true (⚠️ Dangerous, see call_model_method)false, true

*Either ODOO_API_KEY or both ODOO_USER and ODOO_PASSWORD are required. In YOLO mode, ODOO_USER is required even when using an API key.

Notes:

  • If database listing is restricted on your server, you must specify ODOO_DB
  • API key authentication is recommended for better security
  • The server also loads environment variables from a .env file in the working directory

Advanced Configuration

VariableDefaultDescription
ODOO_MCP_DEFAULT_LIMIT10Default number of records returned per search
ODOO_MCP_MAX_LIMIT100Maximum allowed record limit per request
ODOO_MCP_MAX_SMART_FIELDS15Maximum fields returned by smart field selection
ODOO_MCP_LOG_LEVELINFOLog level (DEBUG, INFO, WARNING, ERROR, CRITICAL)
ODOO_MCP_LOG_JSONfalseEnable structured JSON log output
ODOO_MCP_LOG_FILEβ€”Path for rotating log file (10 MB, 5 backups)
ODOO_MCP_LOG_FORMATβ€”Custom Python logging format string (default: %(asctime)s - %(name)s - %(levelname)s - %(message)s)
ODOO_MCP_SLOW_OPERATION_THRESHOLD_MS1000Threshold in milliseconds above which an operation is logged as slow
ODOO_MCP_TRANSPORTstdioTransport type (stdio, streamable-http)
ODOO_MCP_HOSTlocalhostHost to bind for HTTP transport
ODOO_MCP_PORT8000Port to bind for HTTP transport
ODOO_MCP_ALLOWED_HOSTSβ€”Comma-separated Host headers to accept for HTTP transport (DNS-rebinding protection). Set when running streamable-http behind a reverse proxy that forwards an external host, e.g. odoo.example.com,localhost. IPv6 literals may be bracketed or bare ([::1]:8000, ::1). Unset, protection is only auto-enabled for a loopback bind β€” binding any other host (e.g. 0.0.0.0) runs with no Host/Origin validation at all.
ODOO_MCP_SESSION_IDLE_TIMEOUTβ€”Seconds of inactivity before a streamable-http session is closed and its server-side state freed, e.g. 600. Unset means sessions never expire.
ODOO_MCP_MAX_BINARY_SIZE52428800Maximum bytes returned by a single binary/attachment resources/read. Checked before the payload is fetched (a bin_size probe for record fields, the stored file_size for attachments), so an oversized read is refused with a clean error instead of being pulled into memory and re-encoded to base64 for the wire.

Transport Options

The server supports multiple transport protocols for different use cases:

1. stdio (Default)

Standard input/output transport - used by desktop AI applications like Claude Desktop.

# Default transport - no additional configuration needed
uvx mcp-server-odoo

2. streamable-http

Standard HTTP transport for REST API-style access and remote connectivity.

⚠️ Security: this transport has no built-in client authentication. Any client that can reach the port can use every tool and resource with the Odoo credentials the server holds β€” including writes in YOLO full-access mode. Keep the default localhost bind unless the network is trusted, and front the server with an authenticating reverse proxy (e.g. nginx with basic auth or OAuth) for remote access. The server logs a warning when binding a non-loopback host.

# Run with HTTP transport (localhost only β€” safe default)
uvx mcp-server-odoo --transport streamable-http --port 8000

# Binding 0.0.0.0 exposes the server to the network β€” see the security note above
uvx mcp-server-odoo --transport streamable-http --host 0.0.0.0 --port 8000

# Or use environment variables
export ODOO_MCP_TRANSPORT=streamable-http
export ODOO_MCP_HOST=0.0.0.0
export ODOO_MCP_PORT=8000
uvx mcp-server-odoo

The HTTP endpoint will be available at: http://localhost:8000/mcp/

Note: SSE (Server-Sent Events) transport has been deprecated in MCP protocol version 2025-03-26. Use streamable-http transport instead for HTTP-based communication. Requires MCP library v1.27.0 or higher.

Running streamable-http transport for remote access
{
  "mcpServers": {
    "odoo-remote": {
      "command": "uvx",
      "args": ["mcp-server-odoo", "--transport", "streamable-http", "--port", "8080"],
      "env": {
        "ODOO_URL": "https://your-odoo-instance.com",
        "ODOO_API_KEY": "your-api-key-here",
        "ODOO_DB": "your-database-name"
      }
    }
  }
}

Setting up Odoo

  1. Install the MCP module:

    • Download the mcp_server module
    • Install it in your Odoo instance
    • Navigate to Settings > MCP Server
  2. Enable models for MCP access:

    • Go to Settings > MCP Server > Enabled Models
    • Add models you want to access (e.g., res.partner, product.product)
    • Configure permissions (read, write, create, delete) per model
  3. Generate an API key:

    • Go to Settings > Users & Companies > Users
    • Select your user
    • Under the "API Keys" tab, create a new key
    • Copy the key for your MCP configuration

YOLO Mode (Development/Testing Only) ⚠️

YOLO mode allows the MCP server to connect directly to any standard Odoo instance without requiring the MCP module. This mode bypasses all MCP security controls and is intended ONLY for development, testing, and demos.

🚨 WARNING: Never use YOLO mode in production environments!

YOLO Mode Levels

  1. Read-Only Mode (ODOO_YOLO=read):

    • Allows all read operations (search, read, count)
    • Blocks all write operations (create, update, delete)
    • Safe for demos and testing
    • Shows "READ-ONLY" indicators in responses
  2. Full Access Mode (ODOO_YOLO=true):

    • Allows ALL operations without restrictions
    • Full CRUD access to all models
    • EXTREMELY DANGEROUS - use only in isolated environments
    • Shows "FULL ACCESS" warnings in responses

YOLO Mode Configuration

Read-Only YOLO Mode (safer for demos)
{
  "mcpServers": {
    "odoo-demo": {
      "command": "uvx",
      "args": ["mcp-server-odoo"],
      "env": {
        "ODOO_URL": "http://localhost:8069",
        "ODOO_USER": "admin",
        "ODOO_PASSWORD": "admin",
        "ODOO_DB": "demo",
        "ODOO_YOLO": "read"
      }
    }
  }
}
Full Access YOLO Mode (⚠️ use with extreme caution)
{
  "mcpServers": {
    "odoo-test": {
      "command": "uvx",
      "args": ["mcp-server-odoo"],
      "env": {
        "ODOO_URL": "http://localhost:8069",
        "ODOO_USER": "admin",
        "ODOO_PASSWORD": "admin",
        "ODOO_DB": "test",
        "ODOO_YOLO": "true"
      }
    }
  }
}

When to Use YOLO Mode

βœ… Appropriate Uses:

  • Local development with test data
  • Quick demos with non-sensitive data
  • Testing MCP clients before installing the MCP module
  • Prototyping in isolated environments

❌ Never Use For:

  • Production environments
  • Instances with real customer data
  • Shared development servers
  • Any environment with sensitive information

YOLO Mode Security Notes

  • Connects directly to Odoo's standard XML-RPC endpoints
  • Bypasses all MCP access controls and model restrictions
  • No rate limiting is applied
  • All operations are logged but not restricted
  • Model listing shows 200+ models instead of just enabled ones

Usage Examples

Once configured, you can ask Claude:

Search & Retrieve:

  • "Show me all customers from Spain"
  • "Find products with stock below 10 units"
  • "List today's sales orders over $1000"
  • "Search for unpaid invoices from last month"
  • "Count how many active employees we have"
  • "Show me the contact information for Microsoft"

Create & Manage:

  • "Create a new customer contact for Acme Corporation"
  • "Add a new product called 'Premium Widget' with price $99.99"
  • "Create a calendar event for tomorrow at 2 PM"
  • "Update the phone number for customer John Doe to +1-555-0123"
  • "Change the status of order SO/2024/001 to confirmed"
  • "Delete the test contact we created earlier"

Available Tools

search_records

Search for records in any Odoo model with filters.

{
  "model": "res.partner",
  "domain": [["is_company", "=", true], ["country_id.code", "=", "ES"]],
  "fields": ["name", "email", "phone"],
  "limit": 10
}

Field Selection Options:

  • Omit fields or set to null: Returns smart selection of common fields
  • Specify field list: Returns only those specific fields
  • An empty list [] is treated like null (smart defaults)
  • Use ["__all__"]: Returns all fields (use with caution) β€” credential-like fields are withheld and listed in the response's note; request them explicitly by name if needed

get_record

Retrieve a specific record by ID.

{
  "model": "res.partner",
  "record_id": 42,
  "fields": ["name", "email", "street", "city"]
}

Field Selection Options:

  • Omit fields or set to null: Returns smart selection of common fields with metadata
  • Specify field list: Returns only those specific fields
  • An empty list [] is treated like null (smart defaults)
  • Use ["__all__"]: Returns all fields β€” credential-like fields are withheld and noted in the response metadata; request them explicitly by name if needed

Responses also include related_summaries: display names for one2many/many2many collections holding at most 5 ids, so small relations are readable without extra lookups.

get_fields

Describe a model's fields β€” type, label, required/readonly, relation target, and selection options. Use it to discover a model's schema before reading or writing records. Omit attributes for the curated default set (type, string, required, readonly, relation, selection); an explicit list replaces the curated set β€” include the defaults in your list if you still need them (e.g. ["type", "string", "help", "store"]). Omit field_names to describe every field on the model. An empty list [] for either parameter is treated like omitting it.

{
  "model": "res.partner",
  "field_names": ["name", "email", "parent_id"]
}

get_current_context

Return the current session context: the connected user, their timezone, the active company plus any other allowed companies, and UTC datetime-handling guidance. Useful when unsure which user or company a request runs as, or how to interpret datetimes. Spec-compliant clients also receive this context through the initialize response instructions.

{}

list_models

List all models enabled for MCP access.

{}

list_resource_templates

List available resource URI templates and their patterns.

{}

create_record

Create a new record in Odoo.

{
  "model": "res.partner",
  "values": {
    "name": "New Customer",
    "email": "customer@example.com",
    "is_company": true
  }
}

update_record

Update an existing record.

{
  "model": "res.partner",
  "record_id": 42,
  "values": {
    "phone": "+1234567890",
    "website": "https://example.com"
  }
}

delete_record

Delete a record from Odoo.

{
  "model": "res.partner",
  "record_id": 42
}

post_message

Post a message to a record's chatter (mail.thread). subtype="note" (default) is an internal log; subtype="comment" notifies followers. Set body_is_html=true for HTML markup. Optional subject sets a message subject line; optional partner_ids and attachment_ids reference existing partners and attachments.

{
  "model": "res.partner",
  "record_id": 42,
  "body": "Called customer, will follow up Tuesday"
}
{
  "model": "sale.order",
  "record_id": 17,
  "body": "<p>Shipping confirmed for Monday</p>",
  "subtype": "comment",
  "body_is_html": true
}

aggregate_records

Server-side aggregation. Use this whenever the question is "totals/counts/groupings" rather than "list of records" β€” it pushes the work down to PostgreSQL instead of pulling raw rows. Dispatches to formatted_read_group on Odoo 19+ (the new dedicated method) and falls back to read_group with response normalization on older versions. Callers see a consistent response shape on every supported version. When aggregates is omitted, defaults to ["__count"] so each group always carries a count. When more groups exist beyond the requested page, the response sets has_more: true and a next_hint with the follow-up offset.

{
  "model": "sale.order",
  "groupby": ["date_order:month"],
  "aggregates": ["amount_total:sum"],
  "domain": [["state", "in", ["sale", "done"]]]
}
{
  "model": "res.partner",
  "groupby": ["country_id"]
}

call_model_method

Generic XML-RPC execute_kw escape hatch β€” invokes public business methods, for workflow actions not covered by CRUD (post invoice, confirm sale order, validate picking, etc.). Available only when both ODOO_YOLO=true (full YOLO) and ODOO_MCP_ENABLE_METHOD_CALLS=true are set; otherwise the tool is not registered. Only public ASCII Python identifiers are accepted as method names β€” dotted, dashed, whitespace, non-ASCII, and _-prefixed names are rejected.

Some calls are blocked for safety even in full YOLO mode:

  • ir.actions.* / ir.cron models β€” their methods run with elevated privileges (server actions, scheduled jobs)
  • run / method_direct_trigger on any model β€” same escalation risk via proxies
  • ORM CRUD/data-access primitives (create, write, unlink, read, search*, copy, sudo, ...) β€” use the dedicated tools instead
  • web_* methods β€” the web-client data-access family

List results are truncated to 100 items.

[!WARNING] This tool can still invoke destructive workflow methods (e.g. button_draft, action_cancel, toggle_active, custom methods). Enable only in trusted environments where you accept the blast radius. Odoo's record rules and ACLs still apply for the authenticated user.

{
  "model": "account.move",
  "method": "action_post",
  "arguments": [[42]]
}
{
  "model": "sale.order",
  "method": "action_confirm",
  "arguments": [[7]],
  "keyword_arguments": {"context": {"lang": "en_US"}}
}

Smart Field Selection

When you omit the fields parameter (or set it to null), the server automatically selects the most relevant fields for each model using a scoring algorithm:

  • Essential fields like id, name, display_name, and active are always included
  • Business-relevant fields (state, amount, email, phone, partner, etc.) are prioritized
  • Technical fields (message threads, activity tracking, website metadata) are excluded
  • Expensive fields (binary, HTML, large text) are skipped; computed non-stored fields are deprioritized
  • Credential-like fields (names ending in *password, *_pass like smtp_pass, passwd, *secret, *_token, *apikey, or a *_key compound such as api_key/secret_key) are ex

Files in the repo

Repository payloadβ€’13 top-level entries
  • .github
  • mcp_server_odoo
  • tests
  • .dockerignore
  • .env.example
  • .gitignore
  • CHANGELOG.md
  • CONTRIBUTING.md
  • Dockerfile
  • LICENSE
  • pyproject.toml
  • README.md
  • uv.lock

Discussion (0)

Ask about usage, or say what you built with it

Sign in to join the discussion.

No comments yet. Be the first to say what this is good for.

More connectors

Real-time global intelligence dashboard. AI-powered news aggregation, geopolitical monitoring, and infrastructure tracking in a unified situational awareness interface

86k

High-performance code intelligence MCP server. Indexes codebases into a persistent knowledge graph β€” average repo in milliseconds. 158 languages, sub-ms queries, 99% fewer tokens. Single static binary, zero dependencies.

43k

Universal provider proxy for OpenAI Codex & Claude Code β€” use any LLM (Claude, Gemini, Grok, DeepSeek, Ollama…) with Codex CLI, App, SDK, and Claude Code

14k
okf-memory/
okf-agent-memory

Git-native persistent memory for AI coding agents. Implements Google OKF v0.2 with sub-300Β΅s in-memory BM25 search, embedded MCP server, and progressive disclosure. Slashes token bloat by 80% with zero external databases or dependencies. Built in pure Go.

547
tirth8205/
code-review-graph

Local-first code intelligence graph for MCP and CLI. Builds a persistent map of your codebase so AI coding tools read only what matters, with benchmarked context reductions on reviews and large-repo workflows.

31k
2akouwu/
reverify

Stop your AI from making things up β€” it proposes, deterministic tools decide, every claim checked against ground truth with evidence. Grounded facts and context survive resets. Reverse engineering is the proving ground. MCP server + CLI.

1.1k