> ## Documentation Index
> Fetch the complete documentation index at: https://usemci.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Structure

> Learn how to organize MCI projects with entry files, toolsets, MCP server caching, and basic templating patterns

# MCI Structure

This document explains the structural organization of MCI projects, including entry files, toolsets, MCP server caching, and basic templating patterns.

## Entry Files

MCI projects start with one or more **entry files** located in the root of your project directory. These are the main schema files that define your tool collections.

### Single Entry File

The simplest structure uses a single entry file:

```
my-project/
├── mci.json           # Main entry file
├── mci/               # Toolsets directory (optional)
│   └── weather.mci.json
└── src/               # Your application code
```

**Example: `mci.json`**

```json theme={null}
{
  "schemaVersion": "1.0",
  "metadata": {
    "name": "My Application Tools"
  },
  "tools": [
    {
      "name": "main_tool",
      "description": "Primary tool for the application",
      "execution": {
        "type": "text",
        "text": "Main application output"
      }
    }
  ]
}
```

### Multiple Entry Files

You can have multiple entry files, each creating a specific set of tools for different purposes:

```
my-project/
├── api-tools.mci.json         # API-related tools
├── dev-tools.mci.json         # Development tools
├── production-tools.mci.json  # Production-only tools
├── mci/
│   ├── database.mci.json
│   ├── logging.mci.json
│   └── monitoring.mci.json
└── src/
```

**Example: Multiple contexts for different environments**

**api-tools.mci.json:**

```json theme={null}
{
  "schemaVersion": "1.0",
  "metadata": {
    "name": "API Tools"
  },
  "toolsets": [{ "name": "database" }, { "name": "logging" }],
  "tools": [
    {
      "name": "api_health_check",
      "execution": {
        "type": "http",
        "url": "https://api.example.com/health"
      }
    }
  ]
}
```

**dev-tools.mci.json:**

```json theme={null}
{
  "schemaVersion": "1.0",
  "metadata": {
    "name": "Development Tools"
  },
  "toolsets": [
    { "name": "database" },
    { "name": "logging" },
    { "name": "monitoring" }
  ],
  "tools": [
    {
      "name": "run_tests",
      "execution": {
        "type": "cli",
        "command": "pytest",
        "args": ["--verbose"]
      }
    }
  ]
}
```

**Key Points:**

* Each entry file is independent and creates its own set of tools
* Entry files can share toolsets from the `./mci` directory
* Use multiple entry files to organize tools by environment, team, or purpose
* No limit on the number of entry files (1, 3, 10, or more)
* Each entry file must be loaded separately by the client; multiple entry files are not automatically merged and each requires its own MCIClient instance.

## Automatic .env File Loading

MCI automatically loads environment variables from `.env` and `.env.mci` files when loading your MCI schema. This provides a convenient way to manage environment-specific configuration without manually setting variables.

**Automatic Detection:**

* When you run any MCI command (`run`, `list`, `validate`, etc.), MCI looks for environment files in:
  1. The project root directory (same location as your `mci.json` or `mci.yaml`)
  2. The `./mci` directory

**File Priority:**

* MCI prioritizes `.env.mci` files (MCI-specific configs) over `.env` files (general configs)
* **Important:** When `.env.mci` files exist, `.env` files are **not loaded** at all
* This allows you to keep MCI-specific environment variables separate from general project variables

**Loading Behavior:**

* **If `.env.mci` files exist:** Only `.env.mci` files are loaded
  1. `./mci/.env.mci` - Library MCI-specific configs
  2. Project root `.env.mci` - Project MCI-specific configs (higher priority)
* **If no `.env.mci` files exist:** `.env` files are loaded instead
  1. `./mci/.env` - Library general defaults
  2. Project root `.env` - Project-level configs (higher priority)
* **Then:** System environment variables and explicit env\_vars override all file-based configs

**Full Precedence Order (lowest to highest):**

1. File-based configs (`.env.mci` files if they exist, otherwise `.env` files)
   * From `./mci/` directory first
   * Then from project root
2. System environment variables (set via `export` or shell config)
3. Environment variables passed via CLI or code (highest priority)

**Example .env file:**

```bash theme={null}
# .env or .env.mci file in project root
API_KEY=your-api-key-here
BASE_URL=https://api.example.com
DEBUG=false

# Comments are supported
# Blank lines are ignored

# Export keyword is optional (automatically stripped)
export OPTIONAL_VAR=value
```

**Example directory structure:**

```
my-project/
├── .env.mci               # MCI-specific variables (if present, .env ignored)
├── .env                   # General project variables (only if .env.mci absent)
├── mci.json               # Your MCI schema
└── mci/
    ├── .env.mci           # Library MCI-specific (if present, ./mci/.env ignored)
    ├── .env               # Library defaults (only if ./mci/.env.mci absent)
    └── weather.mci.json   # Your toolsets
```

**Example: Using .env.mci files**

```bash theme={null}
# Scenario 1: Only .env.mci files present
# ./mci/.env.mci
API_KEY=mci-library-key
LIBRARY_VAR=lib-value

# .env.mci (project root)
API_KEY=mci-project-key    # Overrides ./mci/.env.mci
MCI_SPECIFIC=mci-value

# Result: MCI will use:
# API_KEY=mci-project-key (from root .env.mci)
# LIBRARY_VAR=lib-value (from ./mci/.env.mci)
# MCI_SPECIFIC=mci-value (from root .env.mci)
```

**Example: Using .env files (no .env.mci)**

```bash theme={null}
# Scenario 2: Only .env files present
# ./mci/.env
API_KEY=default-key
LIBRARY_VAR=lib-value

# .env (project root)
API_KEY=project-key        # Overrides ./mci/.env
PROJECT_VAR=proj-value

# Result: MCI will use:
# API_KEY=project-key (from root .env)
# LIBRARY_VAR=lib-value (from ./mci/.env)
# PROJECT_VAR=proj-value (from root .env)
```

**Notes:**

* .env files are completely optional - MCI works fine without them
* No error if .env files are missing
* Use `.env.mci` for MCI-specific configurations to keep them completely separate from general project configs
* When `.env.mci` exists, `.env` is ignored (not merged)
* You can disable auto-loading by setting `auto_load_dotenv=False` when using the MCI library programmatically
* .env files should NOT be committed to version control if they contain secrets

## Toolsets Directory

Toolsets are stored in the `./mci` directory by default. This can be customized using the `libraryDir` field.

### Default Structure

```
my-project/
├── main.mci.json      # Entry file
└── mci/               # Default toolsets directory
    ├── weather.mci.json
    ├── database.mci.json
    ├── github.mci.json
    └── monitoring.mci.json
```

### Custom Library Directory

You can use a different directory name:

```json theme={null}
{
  "schemaVersion": "1.0",
  "libraryDir": "./toolsets", // Custom directory
  "toolsets": [{ "name": "weather" }]
}
```

```
my-project/
├── main.mci.json
└── toolsets/          # Custom toolsets directory
    └── weather.mci.json
```

### Nested Toolset Organization

Organize toolsets in subdirectories:

```
my-project/
└── mci/
    ├── external/
    │   ├── github.mci.json
    │   ├── slack.mci.json
    │   └── weather.mci.json
    ├── internal/
    │   ├── database.mci.json
    │   ├── logging.mci.json
    │   └── monitoring.mci.json
    └── mcp/            # MCP cache (auto-generated)
        ├── filesystem.mci.json
        └── memory.mci.json
```

**Loading nested toolsets:**

```json theme={null}
{
  "toolsets": [
    { "name": "external/github" },
    { "name": "external/weather" },
    { "name": "internal/database" }
  ]
}
```

## MCP Tools Cache

When you register MCP servers in your schema, MCI automatically caches the tools in a special `mcp` subdirectory within your toolsets directory.

### Cache Location

```
my-project/
├── main.mci.json
└── mci/
    ├── weather.mci.json      # Regular toolset
    ├── database.mci.json     # Regular toolset
    └── mcp/                  # MCP cache directory
        ├── filesystem.mci.json
        ├── github.mci.json
        └── memory.mci.json
```

### How It Works

1. **Register MCP Server** in your entry file:

```json theme={null}
{
  "schemaVersion": "1.0",
  "mcp_servers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/workspace"]
    }
  }
}
```

2. **First Load**: MCI connects to the MCP server, fetches all tools, and saves them to `./mci/mcp/filesystem.mci.json`

3. **Subsequent Loads**: MCI uses the cached file instead of connecting to the server (much faster)

4. **Cache File Example** (`./mci/mcp/filesystem.mci.json`):

```json theme={null}
{
  "schemaVersion": "1.0",
  "metadata": {
    "name": "filesystem MCP Server",
    "description": "Auto-generated toolset from MCP server"
  },
  "expiresAt": "2024-02-15T10:30:00Z",
  "tools": [
    {
      "name": "read_file",
      "description": "Read contents of a file",
      "execution": {
        "type": "mcp",
        "serverName": "filesystem",
        "toolName": "read_file"
      }
    },
    {
      "name": "write_file",
      "description": "Write content to a file",
      "execution": {
        "type": "mcp",
        "serverName": "filesystem",
        "toolName": "write_file"
      }
    }
  ]
}
```

### Cache Management

**Expiration**: Caches expire after a configurable number of days (default: 30):

```json theme={null}
{
  "mcp_servers": {
    "filesystem": {
      "command": "npx",
      "args": ["..."],
      "config": {
        "expDays": 7 // Refresh every 7 days
      }
    }
  }
}
```

**Manual Refresh**: Delete cache files to force re-fetch:

```bash theme={null}
rm -rf ./mci/mcp/
```

**Git Ignore**: Add MCP cache to `.gitignore`:

```
mci/mcp/
```

## Basic Templating

MCI supports templating in all schema files using the `{{}}` syntax. This allows dynamic values from environment variables and provides default fallbacks.

### Environment Variable Templating

**Syntax**: `{{env.VARIABLE_NAME}}`

```json theme={null}
{
  "tools": [
    {
      "name": "api_call",
      "execution": {
        "type": "http",
        "url": "{{env.API_BASE_URL}}/users",
        "auth": {
          "type": "apiKey",
          "in": "header",
          "name": "X-API-Key",
          "value": "{{env.API_KEY}}"
        }
      }
    }
  ]
}
```

### Default Values with Pipe Operator

**Syntax**: `{{env.VARIABLE_NAME|'default_value'}}`

The pipe operator (`|`) allows you to specify a default value if the environment variable is not set:

```json theme={null}
{
  "tools": [
    {
      "name": "connect_db",
      "execution": {
        "type": "cli",
        "command": "psql",
        "args": [
          "-h",
          "{{env.DB_HOST|'localhost'}}",
          "-p",
          "{{env.DB_PORT|'5432'}}",
          "-U",
          "{{env.DB_USER|'postgres'}}",
          "-d",
          "{{env.DB_NAME|'myapp'}}"
        ]
      }
    }
  ]
}
```

**Without environment variables:**

* `{{env.DB_HOST|'localhost'}}` → `"localhost"`
* `{{env.DB_PORT|'5432'}}` → `"5432"`
* `{{env.DB_USER|'postgres'}}` → `"postgres"`

**With environment variables set:**

* `{{env.DB_HOST|'localhost'}}` → `"production.db.example.com"`
* `{{env.DB_PORT|'5432'}}` → `"3306"`

> Note: This allows any amount of vars (but keep it under 5, please): `{{env.DB_HOST|env.EXTERNAL_DB_HOST|'localhost'}}`

### MCI File Templating Examples

#### Example 1: API Configuration with Defaults

```json theme={null}
{
  "schemaVersion": "1.0",
  "tools": [
    {
      "name": "fetch_users",
      "execution": {
        "type": "http",
        "method": "GET",
        "url": "{{env.API_URL|'https://api.example.com}}/users'",
        "headers": {
          "Authorization": "Bearer {{env.API_TOKEN}}",
          "Accept": "application/json"
        },
        "timeout_ms": "{{env.REQUEST_TIMEOUT|'5000'}}"
      }
    }
  ]
}
```

#### Example 2: CLI Tools with Environment Defaults

```json theme={null}
{
  "schemaVersion": "1.0",
  "tools": [
    {
      "name": "deploy_app",
      "execution": {
        "type": "cli",
        "command": "{{env.DEPLOY_TOOL|'kubectl'}}",
        "args": [
          "apply",
          "-f",
          "{{env.CONFIG_PATH|'./k8s/deployment.yaml'}}",
          "--namespace",
          "{{env.NAMESPACE|'default'}}"
        ],
        "cwd": "{{env.PROJECT_ROOT|'.'}}"
      }
    }
  ]
}
```

#### Example 3: MCP Server with Template Defaults

```json theme={null}
{
  "schemaVersion": "1.0",
  "mcp_servers": {
    "filesystem": {
      "command": "{{env.MCP_RUNNER|'npx'}}",
      "args": [
        "-y",
        "@modelcontextprotocol/server-filesystem",
        "{{env.WORKSPACE_PATH|'/tmp'}}"
      ],
      "env": {
        "LOG_LEVEL": "{{env.LOG_LEVEL|'info'}}",
        "MAX_FILE_SIZE": "{{env.MAX_FILE_SIZE|'10485760'}}"
      }
    }
  }
}
```

#### Example 4: Toolset Reference with Filtering

```json theme={null}
{
  "schemaVersion": "1.0",
  "libraryDir": "{{env.TOOLSETS_DIR|'./mci'}}",
  "toolsets": [
    {
      "name": "weather",
      "filter": "only",
      "filterValue": "get_weather,get_forecast"
    },
    {
      "name": "database",
      "filter": "withoutTags",
      "filterValue": "destructive"
    }
  ]
}
```

### Template Usage in Different Contexts

**1. Entry Files** - Use templates in the main schema:

```json theme={null}
{
  "libraryDir": "{{env.MCI_LIB|'./mci'}}",
  "directoryAllowList": [
    "{{env.DATA_DIR|'./data'}}",
    "{{env.CONFIG_DIR|'./config'}}"
  ]
}
```

**2. Toolset Files** - Cannot use `libraryDir` or top-level config, but can use templates in tool definitions:

```json theme={null}
{
  "schemaVersion": "1.0",
  "tools": [
    {
      "name": "process_data",
      "execution": {
        "type": "file",
        "path": "{{env.TEMPLATE_PATH|'./templates'}}/report.txt"
      }
    }
  ]
}
```

**3. MCP Servers** - Use templates for credentials and paths:

```json theme={null}
{
  "mcp_servers": {
    "api_service": {
      "type": "http",
      "url": "{{env.MCP_URL|'http://localhost:8000/mcp}}'",
      "headers": {
        "Authorization": "Bearer {{env.MCP_TOKEN}}"
      }
    }
  }
}
```

## Best Practices

### 1. Use Descriptive Entry File Names

```
✓ Good:
  - api-tools.mci.json
  - dev-environment.mci.json
  - production-monitoring.mci.json

✗ Avoid:
  - tools.json
  - config.json
  - my-stuff.json
```

### 2. Organize Toolsets by Domain

```
mci/
├── apis/
│   ├── github.mci.json
│   ├── weather.mci.json
│   └── slack.mci.json
├── databases/
│   ├── postgres.mci.json
│   └── redis.mci.json
└── utilities/
    ├── logging.mci.json
    └── monitoring.mci.json
```

### 3. Use Environment Variables for Secrets

```json theme={null}
{
  "tools": [
    {
      "execution": {
        "type": "http",
        "auth": {
          "type": "apiKey",
          "value": "{{env.API_KEY}}" // ✓ Good
          // "value": "sk-1234567890"  // ✗ Never hardcode secrets
        }
      }
    }
  ]
}
```

### 4. Provide Sensible Defaults

```json theme={null}
{
  "execution": {
    "type": "cli",
    "command": "{{env.PYTHON_BIN|'python3'}}", // ✓ Default to python3
    "timeout_ms": "{{env.TIMEOUT|'30000'}}" // ✓ Default timeout
  }
}
```

### 5. Document Your Entry Files

```json theme={null}
{
  "schemaVersion": "1.0",
  "metadata": {
    "name": "Production API Tools",
    "description": "Tools for production API operations. Requires API_KEY and DB_URL env vars.",
    "version": "2.1.0",
    "authors": ["Platform Team"]
  }
}
```

## Summary

* **Entry Files**: Main schema files in your project root that define tool collections
* **Multiple Entry Files**: Use as many as needed for different environments or purposes
* **Toolsets Directory**: Default is `./mci`, customizable via `libraryDir`
* **MCP Cache**: Auto-generated in `./mci/mcp/` when MCP servers are registered
* **Templating**: Use `{{env.VAR}}` for environment variables, `{{env.VAR|default}}` for defaults
* **Organization**: Group toolsets by domain, use descriptive names, and document your schemas
