Provider-agnostic natural language AI interface to interact with complex analytical models
Project description
Explicator
Explicator bridges the gap between complex analytical models and the people who need to understand them. Ask a question in plain English, it identifies the right scenarios to run, executes them against your model, and returns a clear explanation of what the results mean. No model expertise required.
Provider-agnostic by design, Explicator works with Claude, Azure OpenAI, Copilot, or any LLM your organisation uses.
Project Structure
explicator/
├── src/explicator/
│ ├── domain/ # Core data structures and abstract ports
│ │ ├── models.py # ScenarioDefinition, ScenarioResult, ModelSchema, etc.
│ │ └── ports.py # ScenarioRunner, ModelRepository (abstract interfaces)
│ ├── application/
│ │ └── service.py # ModelService — single entry point for all business logic
│ ├── adapters/
│ │ ├── cli/ # Click-based CLI adapter
│ │ ├── mcp_server/ # FastMCP server adapter (for Claude Desktop / MCP clients)
│ │ └── data/ # Infrastructure adapters (in-memory implementations)
│ ├── ai/
│ │ ├── tools/ # Tool definitions in OpenAI function-calling JSON schema format
│ │ ├── providers/ # Provider adapters: Claude, Azure OpenAI (+ abstract base)
│ │ └── dispatcher.py # Shared tool dispatcher (provider-agnostic)
│ └── config.py # Configuration via environment variables
├── examples/
│ └── demo_model/ # Bond portfolio risk model — shows how to wire Explicator
├── docs/
│ └── model_schema.md # Rich domain description for AI context
└── tests/
├── unit/
└── integration/
explicator is the library — install it as a dependency and build your model on top of it, just as you would with fastapi or click. Your model code lives in your own project; explicator provides the service layer, AI interface, CLI, and MCP server.
Quick Start
1. Install
pip install -e ".[claude,dev]"
For Azure OpenAI instead:
pip install -e ".[azure,dev]"
2. Configure
cp .env.example .env
# Edit .env and set your API key and provider
3. Run the demo CLI
# List scenarios
explicator --service examples.demo_model.model:build_service scenarios
# Run a scenario
explicator --service examples.demo_model.model:build_service run base_case
# Run with an override
explicator --service examples.demo_model.model:build_service run base_case -o credit_spread_ig=2.5
# Compare two scenarios
explicator --service examples.demo_model.model:build_service compare base_case credit_stress
# Chat with an AI about the model
explicator --service examples.demo_model.model:build_service chat
Set EXPLICATOR_SERVICE in your environment to avoid repeating the flag:
export EXPLICATOR_SERVICE=examples.demo_model.model:build_service
explicator run base_case
explicator chat "what happens to duration in the stagflation scenario?"
4. Start the MCP Server
With the demo model:
uv run mcp dev examples/demo_model/run_mcp.py
Via the entry point:
explicator-mcp examples.demo_model.model:build_service
# or
python -m explicator.adapters.mcp_server examples.demo_model.model:build_service
5. Connect Claude Desktop
Copy claude_desktop_config.json.example into your Claude Desktop config:
{
"mcpServers": {
"explicator": {
"command": "python",
"args": [
"-m",
"explicator.adapters.mcp_server",
"myapp.model:build_service"
],
"env": {
"ANTHROPIC_API_KEY": "your-api-key-here"
}
}
}
}
Then ask Claude things like:
- "Run the credit stress scenario and tell me what happened to portfolio duration."
- "Override the credit spread input to 250bps and rerun the base case."
- "What are the key assumptions in this model?"
- "Compare the stagflation and rates_shock_up scenarios."
Connecting Your Own Model
explicator is a library — your model code lives in your own project. A typical layout:
my-risk-app/
├── pyproject.toml # dependencies = ["explicator[claude]"]
├── .env # ANTHROPIC_API_KEY=...
└── src/myapp/
├── model.py # schema, scenarios, model_fn, build_service()
└── run_mcp.py # calls explicator.run_mcp(service)
# src/myapp/model.py
import explicator
service = explicator.create(
model_fn=my_model_fn,
base_inputs=MY_BASE_INPUTS,
schema=MY_SCHEMA,
scenarios=MY_SCENARIOS,
)
# src/myapp/run_mcp.py
import explicator
from myapp.model import service
if __name__ == "__main__":
explicator.run_mcp(service)
# CLI — point --service at any module:attribute that returns a ModelService
explicator --service myapp.model:service scenarios
explicator --service myapp.model:service run base_case
explicator --service myapp.model:service chat
Explicator uses the ports & adapters pattern. The quickest way to wire up any Python model function:
import explicator
def my_model(inputs: dict) -> dict:
# Your model logic here
return {"metric_a": ..., "metric_b": ...}
service = explicator.create(
model_fn=my_model,
base_inputs=MY_BASE_INPUTS,
schema=MY_SCHEMA,
scenarios=MY_SCENARIOS,
)
if __name__ == "__main__":
explicator.run_mcp(service)
For custom storage or execution backends, implement ScenarioRunner and ModelRepository directly and pass them to ModelService:
from explicator import ModelService
from explicator.domain.ports import ScenarioRunner, ModelRepository
class MyRunner(ScenarioRunner): ...
class MyRepository(ModelRepository): ...
service = ModelService(runner=MyRunner(), repository=MyRepository())
See examples/demo_model/model.py for a complete worked example.
AI Provider Configuration
Set AI_PROVIDER in your environment:
| Value | Provider | Required env vars |
|---|---|---|
claude (default) |
Anthropic Claude | ANTHROPIC_API_KEY |
azure_openai |
Azure OpenAI | AZURE_OPENAI_API_KEY, AZURE_OPENAI_ENDPOINT, AZURE_OPENAI_DEPLOYMENT |
Tool definitions live in src/explicator/ai/tools/definitions.py in OpenAI function-calling
JSON schema format — a single source of truth consumed by all providers.
Running Tests
pytest
Architecture
Explicator enforces strict separation between layers:
- Domain (
domain/) — pure Python dataclasses and abstract interfaces; no framework code - Application (
application/service.py) — business logic; no framework code; tested directly - Adapters (
adapters/) — thin translation layers; CLI and MCP server both callModelService - AI (
ai/) — provider adapters and dispatcher; no business logic; no provider-specific code outside its own module
The MCP server and CLI are parallel entry points into the same application layer. They share no code with each other except through ModelService.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file explicator-0.1.1.tar.gz.
File metadata
- Download URL: explicator-0.1.1.tar.gz
- Upload date:
- Size: 17.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
52229b6afd0b2916e7959f9db135ce4807611c1341d1f48fdeb59bb3418e10aa
|
|
| MD5 |
a6debfe09daa0b6a35d0f43429215d55
|
|
| BLAKE2b-256 |
326cdbaf7f9ac6d68283ab27f843d4f56f2b5a6f935021fac8708868df229aaf
|
File details
Details for the file explicator-0.1.1-py3-none-any.whl.
File metadata
- Download URL: explicator-0.1.1-py3-none-any.whl
- Upload date:
- Size: 27.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6023d015571b31814a645a94927f3dec7d18f8d26f7358e0bbef384efe0da34f
|
|
| MD5 |
48190d205f44a1c39441af2a2ff5fbdc
|
|
| BLAKE2b-256 |
896eb6ba6ecb132a664e59b7857cee11b7142e305f5b25683b11386aa3c8af7f
|