# How mcporter Integration Powers Exa Semantic Search in Agent-Reach

> Discover how mcporter integration securely stores Exa API credentials in Agent-Reach, enabling authenticated semantic search requests. Learn more about this powerful connection.

- Repository: [Pnant/Agent-Reach](https://github.com/Panniantong/Agent-Reach)
- Tags: internals
- Published: 2026-06-06

---

**Agent-Reach uses the mcporter configuration system to securely store Exa API credentials in [`config/mcporter.json`](https://github.com/Panniantong/Agent-Reach/blob/main/config/mcporter.json), which the Exa channel consumes to execute authenticated semantic search requests against the Exa API.**

The **mcporter integration** enables Agent-Reach to interface with Exa’s semantic search engine by externalizing authentication details into a dedicated configuration file. This architecture decouples credential management from search logic, allowing the [`agent_reach/channels/exa.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/exa.py) module to focus solely on API communication and result processing. By routing all Exa-specific requests through this standardized channel, Agent-Reach maintains a clean separation between provider configuration and core search functionality.

## Understanding the mcporter Configuration System

The mcporter system acts as the single source of truth for third-party API authentication within Agent-Reach. Located at [`config/mcporter.json`](https://github.com/Panniantong/Agent-Reach/blob/main/config/mcporter.json), this file stores provider-specific credentials including API keys, base URLs, and organization IDs required for platform access.

During application startup, [`agent_reach/config.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/config.py) loads this JSON file into a global `Config` object. The configuration exposes helper methods such as `Config.get_mcporter()`, which channel implementations call to retrieve their specific authentication parameters without directly accessing the filesystem.

## The Exa Semantic Search Flow

The integration follows a six-stage pipeline that transforms user queries into normalized search results using the Exa semantic engine.

### Configuration Loading

When Agent-Reach initializes, the `Config` class reads [`config/mcporter.json`](https://github.com/Panniantong/Agent-Reach/blob/main/config/mcporter.json) and parses the Exa-specific credentials. This typically includes the `api_key`, optional `organization_id`, and `base_url` parameters. These values remain cached in memory for the application lifecycle, ensuring channels can access credentials without repeated disk I/O.

### Core Routing and Channel Registration

The [`agent_reach/core.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/core.py) module maintains a registry of concrete channel classes inheriting from `BaseChannel`. During initialization, the system discovers and instantiates the Exa channel located in [`agent_reach/channels/exa.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/exa.py). The channel registers itself by implementing the `can_handle()` method, which identifies URLs or query patterns specific to the Exa platform.

### Channel Construction and Authentication

Upon instantiation, the Exa channel constructor retrieves mcporter settings via `Config.get_mcporter()`. It constructs an HTTP client instance and injects the Exa API key into the `Authorization` header of all subsequent requests. This design ensures that authentication logic remains encapsulated within the channel rather than scattered throughout the codebase.

### Executing Semantic Search Requests

The core search functionality resides in the Exa channel's `search(query: str)` method. When invoked, this method sends an HTTP POST request to the Exa endpoint `/v1/search`, including the query string and the `"semantic": true` flag to enable semantic search capabilities. The Exa API returns a JSON payload containing similarity scores and highlighted text snippets.

### Result Normalization

Raw responses from Exa undergo transformation into the common `SearchResult` model defined in [`agent_reach/core.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/core.py). This normalization ensures that downstream components—whether CLI tools, Python libraries, or external agents—receive a uniform data structure regardless of the underlying search provider. The normalized results include standardized fields for title, snippet, URL, and relevance score.

### CLI Integration

The command-line interface in [`agent_reach/cli.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/cli.py) exposes search functionality through the `search` command. When users specify `--provider exa` or when query heuristics match Exa-specific patterns, the CLI forwards the request to the core routing system, which dispatches it to the Exa channel. Results display in formatted tables using the **rich** library.

## Practical Implementation Examples

Configure and use the Exa integration with these implementation patterns.

**1. Configuring mcporter credentials**

Create or edit [`config/mcporter.json`](https://github.com/Panniantong/Agent-Reach/blob/main/config/mcporter.json) to include your Exa API credentials:

```json
{
  "exa": {
    "api_key": "your_exa_api_key_here",
    "base_url": "https://api.exa.ai",
    "organization_id": "optional_org_id"
  }
}

```

**2. Performing semantic searches in Python**

Execute searches programmatically using the Agent-Reach core:

```python
from agent_reach.core import AgentReach

# Initialize with automatic mcporter config loading

agent = AgentReach()

# Execute semantic search via Exa

results = agent.search(
    "recent breakthroughs in large language models", 
    provider="exa"
)

for result in results:
    print(f"{result.title}\n{result.snippet}\nRelevance: {result.score:.2f}\n")

```

**3. Using the CLI interface**

Run semantic searches directly from the terminal:

```bash
python -m agent_reach.cli search "machine learning optimization techniques" --provider exa

```

The CLI renders results in a formatted table showing titles, semantic similarity scores, and content snippets.

## Key Source Files and Architecture

The mcporter integration spans five critical files:

- **[`config/mcporter.json`](https://github.com/Panniantong/Agent-Reach/blob/main/config/mcporter.json)** – Stores Exa API credentials and endpoint configuration. This file acts as the externalized secret management layer.
- **[`agent_reach/config.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/config.py)** – Implements the `Config` class with the `get_mcporter()` method, handling JSON parsing and credential caching.
- **[`agent_reach/channels/exa.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/exa.py)** – Contains the `ExaChannel` class implementing `can_handle()`, `search()`, `read()`, and `check()` methods. This file wires mcporter credentials into HTTP calls to the Exa API.
- **[`agent_reach/core.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/core.py)** – Defines the `BaseChannel` abstract class, the channel registry, and the `SearchResult` normalization model. This module orchestrates request routing between the CLI and specific provider channels.
- **[`agent_reach/cli.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/cli.py)** – Implements the command-line interface that forwards user queries to the core routing system and displays normalized results.

## Summary

- The **mcporter integration** externalizes Exa API credentials into [`config/mcporter.json`](https://github.com/Panniantong/Agent-Reach/blob/main/config/mcporter.json), decoupling authentication from business logic.
- [`agent_reach/config.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/config.py) loads these settings during startup, exposing them via `Config.get_mcporter()` to channel implementations.
- The Exa channel in [`agent_reach/channels/exa.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/exa.py) consumes these credentials to authenticate requests against the Exa `/v1/search` endpoint with semantic search enabled.
- Results undergo normalization into the `SearchResult` model in [`agent_reach/core.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/core.py), providing uniform output regardless of the search provider.
- Both Python API and CLI interfaces leverage this architecture to provide seamless semantic search capabilities.

## Frequently Asked Questions

### What file format does the mcporter configuration use?

The mcporter configuration uses standard JSON format stored at [`config/mcporter.json`](https://github.com/Panniantong/Agent-Reach/blob/main/config/mcporter.json). This file contains nested objects for each supported provider, with the Exa configuration typically including `api_key`, `base_url`, and optional `organization_id` fields. The `Config` class in [`agent_reach/config.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/config.py) parses this file during application initialization and caches the values for runtime access.

### How does Agent-Reach handle Exa API authentication?

The Exa channel retrieves credentials from the mcporter configuration via `Config.get_mcporter()` during construction. It then injects the API key into the `Authorization` header of every HTTP request sent to the Exa API endpoints. This approach keeps authentication logic encapsulated within the channel implementation rather than exposed in user-facing code.

### Can Agent-Reach route queries to multiple search providers simultaneously?

Yes. The core routing system in [`agent_reach/core.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/core.py) maintains a registry of all available channel classes that inherit from `BaseChannel`. While the CLI currently targets single providers via the `--provider` flag, the underlying architecture supports iterating over multiple channels. Each channel independently handles its own mcporter authentication and API communication, allowing for future multi-provider aggregation features.

### Where is the semantic search flag set in the Exa integration?

The semantic search parameter is set within the `search()` method of [`agent_reach/channels/exa.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/exa.py). When constructing the POST request to the `/v1/search` endpoint, the method includes `"semantic": true` in the request payload. This flag instructs the Exa API to perform semantic rather than keyword-based matching, enabling conceptually similar result retrieval.