<p align="center"><a href="https://seequent.com" target="_blank"><picture><source media="(prefers-color-scheme: dark)" srcset="https://developer.seequent.com/img/seequent-logo-dark.svg" alt="Seequent logo" width="400" /><img src="https://developer.seequent.com/img/seequent-logo.svg" alt="Seequent logo" width="400" /></picture></a></p>

<p align="center">
    <a href="https://developer.seequent.com/" target="_blank">Seequent Developer Portal</a>
    &bull; <a href="https://community.seequent.com/group/19-evo" target="_blank">Seequent Community</a>
    &bull; <a href="https://seequent.com" target="_blank">Seequent website</a>
</p>

# Evo MCP 

## Table of contents

- [What is MCP?](#what-is-mcp)
- [What is the Evo MCP server?](#what-is-the-evo-mcp-server)
  - [How teams use Evo MCP](#how-teams-use-evo-mcp)
  - [Server architecture](#server-architecture)
- [Getting started](#getting-started)
  - [Prerequisites](#prerequisites)
  - [Installation](#installation)
- [Connect to Evo MCP](#connect-to-evo-mcp)
  - [VS Code](#vs-code)
  - [Cursor](#cursor)
  - [Additional tips](#additional-tips)
- [Advanced](#advanced)
  - [Testing with FastMCP CLI](#testing-with-fastmcp-cli)
  - [Testing with a Google ADK agent](#testing-with-a-google-adk-agent)
- [Development](#development)
- [Contributing](#contributing)
- [Code of conduct](#code-of-conduct)
- [License](#license)
- [Disclaimer](#disclaimer)
- [Acknowledgements](#acknowledgements)

## What is MCP?

> The Model Context Protocol (MCP) is an open protocol that enables seamless integration between LLM applications and external data sources and tools. Whether you're building an AI-powered IDE, enhancing a chat interface, or creating custom AI workflows, MCP provides a standardized way to connect LLMs with the context they need.
>
> — [Model Context Protocol README](https://github.com/modelcontextprotocol)

An MCP Server is a lightweight program that provides specific features through the Model Context Protocol standard. Applications like chatbots, code editors, and AI tools run MCP clients that each establish a direct connection with an MCP server. Popular MCP clients include agentic code assistants (such as [VS Code](https://code.visualstudio.com) and [Cursor](https://cursor.com)) and conversational tools like Claude Desktop, with more expected in the future. MCP servers can connect to both local and remote data, supplying enriched information that enables AI models to generate more accurate and useful results.

MCP servers are consumable by any MCP client such as VS Code, Claude Desktop, or a Google ADK agent.

## What is the Evo MCP server?

The Evo MCP server is a self-hosted server that provides a secure, standardised interface between your AI tools and the Evo platform. It acts as a bridge, exposing Evo SDK functionality - like access to your workspaces, geoscience objects, and block models - to any AI model or agent you choose.

The server comes packaged with many tools written by Seequent, but it is fully extensible and users are encouraged to add their own tools.

### How teams use Evo MCP

* Workspace management: Create workspaces, summarize objects, snapshot and duplicate workspaces, copy objects between workspaces.
* Geoscience object creation: structured geoscience objects (pointsets, line segments, downhole collections, and downhole intervals) in Evo directly from raw CSV files, automating data validation and schema mapping.

> [!WARNING]
> The Evo MCP server is in early development and functionality is limited. Your feedback on future development is welcome!

### Server architecture

```mermaid
flowchart LR
    Clients["🖥️ MCP Clients<br/>VS Code · Cursor<br/>Claude Desktop · ADK"]
    Clients -- "stdio / streamable HTTP" --> Server
    Server -- HTTPS --> APIs

    subgraph Server["Evo MCP Server (FastMCP)"]
        Tools["Tool Modules<br/>General · Admin<br/>Data · Filesystem"]
        Filter[MCP_TOOL_FILTER]
        Context[EvoContext<br/>per-session or shared]
        Proxy["OIDCProxy<br/>(delegated auth only)"]
        Tools --> Filter --> Context
        Proxy -. "upstream token" .-> Context
    end

    subgraph IMS["Bentley IMS"]
        OIDC[OAuth 2.0 / OIDC]
    end

    subgraph APIs[Evo APIs]
        Discovery[Discovery]
        Workspace[Workspace]
        Object[Object]
    end

    Proxy -- "Proxied OAuth<br/>(delegated)" --> OIDC
    Context -. "Direct OAuth<br/>(managed)" .-> OIDC
```

> See [docs/authentication.md](docs/authentication.md) for detailed sequence diagrams and session lifecycle.

### Key components

| Component | Description |
|-----------|-------------|
| **MCP clients** | Any MCP-compatible application connects to the server over `STDIO` or `streamable HTTP`. |
| **FastMCP server** | The core server runtime that handles MCP protocol, tool registration, and request routing. |
| **Tool modules** | Tools are grouped by category and conditionally registered based on the `MCP_TOOL_FILTER` setting. General tools are always loaded. |
| **EvoContext** | Manages OAuth authentication (with token caching), Evo SDK client initialization, and organization/hub selection. Initialization is lazy — it happens on the first tool call, triggering a browser-based login if needed. |
| **Evo APIs** | The Evo SDK packages (block model, geoscience object, workspace) communicate with Seequent Evo over HTTPS. |

## Getting started

### Prerequisites
- Python 3.10+
- Access to Seequent Evo (https://evo.seequent.com)

### Quick Start with Docker

**Recommended for**: Fast evaluation, containerised deployments, and users who want the easiest setup path.

1. Copy the example environment file:
   ```bash
   cp .env.example .env
   ```
   Then fill in your auth and deployment settings in [Configure your environment](#5-configure-your-environment); `.env.example` shows the available options.
2. Start the server from the published image:
  ```bash
   docker run --rm \
   --env-file .env \
   -e MCP_TRANSPORT=http \
   -e CLIENT_DELEGATED_AUTH=true \
   -e MCP_HTTP_HOST=0.0.0.0 \
   -e MCP_HTTP_PORT=5000 \
   -e MCP_PUBLIC_BASE_URL=http://localhost:5001 \
   -p 5001:5000 \
   ghcr.io/seequentevo/evo-mcp:latest
   ```
  Or to build from source and start with Docker Compose:
   ```bash
   docker compose up --build
   ```
   Note: If you use the legacy Compose CLI, the equivalent command is `docker-compose up`.
   
3. Open `http://localhost:5001/health` to confirm the server is running.


### Installation 

#### 1. Clone this repository
```powershell
git clone https://github.com/SeequentEvo/evo-mcp.git
```

#### 2. Navigate to the root directory
```powershell
cd <path-to-this-repository>
```

#### 3. Create a Python environment

<strong>Option 1: Using `uv` (recommended)</strong>

The Python package manager `uv` makes it easy to set up your Python environment. Visit the [uv website](https://docs.astral.sh/uv/) to learn more.

##### a. Install `uv` (if not already installed)

##### Windows

```powershell
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
```

##### macOS and Linux

```bash
curl -LsSf https://astral.sh/uv/install.sh | sh
```

##### b. Create the Python environment including dependencies
```bash
uv sync
```

<strong>Option 2: Using `pip` and `pyenv`</strong>

If you prefer using `pip` and `pyenv` to manage your Python environment:

##### a. Install `pyenv` (if not already installed)
   - **Windows**: Use [pyenv-win](https://github.com/pyenv-win/pyenv-win#installation)
   - **macOS**: `brew install pyenv`
   - **Linux**: Follow [pyenv installation guide](https://github.com/pyenv/pyenv#installation)


##### b. Install Python 3.10+
   ```bash
   pyenv install 3.10
   pyenv local 3.10
   ```

##### c. Create a virtual environment

```bash
python -m venv .venv
```

##### d. Activate the virtual environment

##### Windows
```powershell
.venv\Scripts\activate
```

##### macOS and Linux

```bash
source .venv/bin/activate
```

##### e. Install dependencies

Install essential runtime dependencies:

```bash
pip install -e .
```

Install dev dependencies along with the essential runtime dependencies:

```bash
pip install -e '.[dev]'
```

#### 4. Choose an MCP transport mode (optional)

The Evo MCP server supports two common transport modes for different use cases.

##### STDIO transport (default)

**Recommended for**: VS Code, Cursor, Claude Desktop, and other integrated MCP clients

`STDIO` (Standard Input/Output) is the default transport mode and is optimised for direct integration with MCP client applications. This transport communicates through standard input and output streams, making it perfect for command-line tools and desktop applications like VS Code and Cursor.
With STDIO transport, the client spawns a new server process for each session and manages its lifecycle. The server reads MCP messages from stdin and writes responses to stdout. This is why STDIO servers don’t stay running - they’re started on-demand by the client.

**Advantages**
- Simpler configuration - client handles connection automatically
- Better performance for local connections
- Directly integrated into VS Code and Cursor workflows
- No network overhead

Configure your client (VS Code, Cursor, etc.) to start the MCP server process. The client will handle all communication via STDIO.

##### Streamable HTTP transport

**Recommended for**: Testing, remote access, programmatic access via FastMCP CLI/scripts, containerised deployments (Docker), and client-delegated shared deployments

HTTP transport turns your MCP server into a web service accessible via a URL. This transport uses the Streamable HTTP protocol, which allows clients to connect over the network. Unlike STDIO where each client gets its own process, an HTTP server can handle multiple clients simultaneously.
For the containerised path, see [Quick Start with Docker](#quick-start-with-docker) section.

The Streamable HTTP protocol provides full bidirectional communication between client and server, supporting all MCP operations including streaming responses. Combined with `CLIENT_DELEGATED_AUTH=true`, HTTP transport supports multiple concurrent user sessions each authenticating with their own Bentley account.

**Advantages**
- Can be accessed via FastMCP CLI, programming languages, or HTTP clients
- Useful for testing and debugging
- Enables remote access to the server
- Simplifies integration with custom tools and scripts
- Ideal for containerised deployments (Docker, Kubernetes)
- Works well in cloud environments and microservices architectures
- Supports concurrent user sessions when `CLIENT_DELEGATED_AUTH=true`

**Limitations**
- Requires separate server process management
- Slightly higher latency due to HTTP overhead

##### Common use cases

| Use case | Recommended transport | `CLIENT_DELEGATED_AUTH` |
|----------|----------------------|-------------------|
| Using VS Code with Copilot | STDIO | `false` |
| Using Cursor with AI | STDIO | `false` |
| Using Claude Desktop | STDIO | `false` |
| Testing tools with FastMCP CLI | HTTP | `false` |
| Remote server access | HTTP | `false` |
| Custom script integration | HTTP | `false` |
| Client-delegated shared server | HTTP | `true` |
| Containerised / Docker deployment | HTTP | `true` (recommended) |


#### 5. Configure your environment

Make a copy of the file `.env.example` and rename it to `.env`. Fill in your app credentials as described below.

##### Evo app credentials
You first need to create a **native app** in the [My apps](https://developer.seequent.com/my-apps) page of the [Seequent Developer Portal]. This app will allow you to sign in with your Bentley account to access Seequent Evo. Visit the [Seequent Developer Portal](https://developer.seequent.com/docs/guides/getting-started/apps-and-tokens) to learn more.

Fill in your app credentials in the `.env` file:
```bash
EVO_CLIENT_ID=your-client-id
EVO_REDIRECT_URL=your-redirect-url
```

When you first use the server it will open your browser so you can sign in with your Bentley account. This gives the server access to any Evo instance and workspace your account has access to.

<details>
<summary><strong>Alternative: Service authentication (for automation/CI)</strong></summary>

If you need to run the server without interactive sign-in (e.g. automation, CI/CD, or background services), you can use a **service app** instead. Create a **service app** in the [My apps](https://developer.seequent.com/my-apps) page of the Seequent Developer Portal and set the following in your `.env` file:

```bash
AUTH_METHOD=client_credentials
EVO_CLIENT_ID=your-service-client-id
EVO_CLIENT_SECRET=your-service-client-secret
```

Note: The service app must be explicitly granted access to your Evo instance and workspaces.

</details>

##### Client-delegated authentication for multi-session scenarios (optional)
When the server is running in HTTP mode, you can choose to enable client-delegated authentication to support multiple sessions with different users/identities. In this mode, each client (VS Code, Cursor, etc.) authenticates separately via OIDCProxy and holds its own token. The server maintains separate Evo sessions per client token. This is suitable for multi-user shared server scenarios where each user needs to authenticate with their own Bentley account and access their own Evo workspaces.


**Definitions**
- **Server-managed auth (default)**: The MCP server is the OAuth client. It handles authentication internally. All clients share the same Evo session and identity. Suitable for single-identity workflows where the server is only accessible to a single user or service account.
- **Client-delegated auth**: Each MCP client (VS Code, Cursor, etc.) is an independent OAuth client. Each client authenticates separately via OIDCProxy and holds its own token. The server maintains separate Evo sessions per client token. Suitable for multi-user shared server scenarios where each user needs to authenticate with their own Bentley account and access their own Evo workspaces.

The authentication flow (server-managed vs. client-delegated) is controlled by three settings: `MCP_TRANSPORT`, `AUTH_METHOD`, and `CLIENT_DELEGATED_AUTH`. The table below outlines the behaviour of the server under the valid combinations of these settings.

| `MCP_TRANSPORT` | `CLIENT_DELEGATED_AUTH` | `AUTH_METHOD` | Behaviour | Client-delegated |
|---|---|---|---|:-:|
| `stdio` | ignored | `native_app` | Server opens a browser for sign-in on first use. Token cached per process. | ❌ |
| `stdio` | ignored | `client_credentials` | Server fetches a service token automatically. No browser interaction. | ❌ |
| `http` | `false` (default) | `native_app` | Server opens a browser for sign-in on first use. All HTTP clients share the same token. | ❌ |
| `http` | `false` (default) | `client_credentials` | Server fetches a service token automatically. All HTTP clients share the same token. | ❌ |
| `http` | `true` | `native_app` | Each MCP client authenticates independently via OAuth browser flow (OIDCProxy). `AUTH_METHOD` is not used. | ✅ |


**Redirect URL configuration:**

  Based on the authentication mode, the redirect URL for OAuth will be configured differently. Ensure you set the correct redirect URL in your [app configuration](https://developer.seequent.com/my-apps) and the correct environment variable in your `.env` file.

  - **Server-managed auth**: ``EVO_REDIRECT_URL`` — used only in managed auth mode where the MCP server will manage the OAuth callback and token storage (e.g. ``http://localhost:3000/signin-callback``). In this mode, the hostname and port combination must be different to the ``MCP_HTTP_HOST:MCP_HTTP_PORT`` to avoid conflicts (e.g. if `MCP_HTTP_HOST=localhost` and `MCP_HTTP_PORT=5000`, use `EVO_REDIRECT_URL=http://localhost:3000/signin-callback`).

  - **Client-delegated auth**: ``OIDCPROXY_REDIRECT_PATH`` — the path on *this* MCP server where IMS sends the OAuth callback in delegated auth mode. The full url will be `http://{MCP_PUBLIC_BASE_URL}/signin-callback` (e.g. `http://localhost:5000/signin-callback` or `http://my.evo.mcp.server.com/signin-callback`). 
   
  **Note**: MCP_PUBLIC_BASE_URL defaults to `http://{MCP_HTTP_HOST}:{MCP_HTTP_PORT}` if not set. The full redirect URL will be `http://{MCP_HTTP_HOST}:{MCP_HTTP_PORT}/signin-callback`. 


##### MCP transport mode (optional)

The Evo MCP server supports two transport modes: **STDIO** and **streamable HTTP**. By default, the server runs in **STDIO** mode which is recommended for local development.

Set `MCP_TRANSPORT` environment variable in `.env` to choose the transport mode:
- `stdio` - Standard input/output (default)
- `http` - Streamable HTTP

```bash
MCP_TRANSPORT=stdio
```

If using HTTP mode, also configure the host and port:
```bash
MCP_TRANSPORT=http
MCP_HTTP_HOST=localhost
MCP_HTTP_PORT=5000
```

When using HTTP mode, the MCP server must be running and reachable at the configured URL. The setup scripts can start it automatically for you, or you can run it manually.

##### MCP tool filtering (optional)

Set `MCP_TOOL_FILTER` environment variable in `.env` to filter available tools:
- `admin` - Workspace/instance management and bulk data operations
- `data` - Object import, download and query operations  
- `all` - All tools (default)

```bash
MCP_TOOL_FILTER=all
```

##### Tool exposure strategy (optional)

Set `MCP_TOOL_STRATEGY` to control how the model discovers and reaches the tool catalog:
- `tool-search` (default) - the catalog is hidden behind two synthetic tools, `search_tools` and `call_tool`. The model searches for the tool it needs, then calls it. This keeps model-exposed toolset small and on-demand. The bootstrap tools `select_instance` and `list_my_instances` stay directly visible so an agent can always find its entry point.
- `none` - the full tool catalog is listed upfront (the historical behavior). Use this as an escape hatch for clients or evals that prefer a flat catalog.

When `tool-search` is active, `MCP_SEARCH_ENGINE` selects the ranking engine:
- `bm25` (default) - relevance ranking over tool names and descriptions. For real agent use (fuzzy, ranked, natural-language tolerant).
- `regex` - pattern matching over tool names and descriptions. Deterministic, reproducible results — same query always returns the same set in the same order. Useful for tests, evals, and demos where you don't want BM25 ranking to shift.



```bash
MCP_TOOL_STRATEGY=tool-search
MCP_SEARCH_ENGINE=bm25
```

## Connect to Evo MCP

Apps like VS Code and Cursor make it easy to connect to MCP servers, whether they are running locally, are available over a local network, or over the internet. VS Code is free to download and use. Cursor requires a paid subscription.

NOTE: Installing any of the MCP client apps described in this section is entirely optional. If you have a favourite MCP client app that you think we should document here, please create a [feature request ticket](https://github.com/SeequentEvo/evo-mcp/issues) and let us know.

### VS Code

#### Installation

VS Code comes in two versions - **VS Code** and **VS Code Insiders**. Install one of these apps before running Evo MCP. 
NOTE: Both of these apps can be installed and used independently.

- Install the regular version of [VS Code](https://code.visualstudio.com/Download) (recommended).
- Install [VS Code Insiders](https://code.visualstudio.com/insiders/) for the most up-to-date experience. VS Code Insiders provides early access to the latest features and improvements for MCP integration. 

#### Configuration

Run the supplied Python script to add the required settings. The script will ask you a series of questions in the console.

**If you set up Python with `uv`:**
```bash
uv run python scripts/setup_mcp.py
```

**If you set up Python with `pip`:**
```bash
python scripts/setup_mcp.py
```

**Manual method**
1. Copy the settings found in `templates/vscode-stdio-config.json`.
  - For HTTP mode, use `templates/vscode-http-config.json` instead.
  - Update the template URL host and port to match `MCP_HTTP_HOST` and `MCP_HTTP_PORT` in your `.env`, and ensure the HTTP server is running.
2. Open the **Command Palette** (press `Cmd+Shift+P` on macOS / `Ctrl+Shift+P` on Windows/Linux).
3. Search for "mcp". Select **MCP: Open User Configuration** to update the user settings.
  ![VS Code Command Palette](images/vscode-command-palette.png)
4. Paste the settings you copied from the template, update the paths to match your local installation, and save the file. NOTE: The JSON template shows Windows file paths but the screenshot below shows macOS file paths. Follow the conventions that suit your operating system. 
  ![VS Code MCP Settings](images/vscode-settings.png)
5. The MCP server will start automatically when accessed by Copilot.

#### Verify the configuration

To verify that the Evo MCP server is correctly configured in VS Code:

1. Click the **Extensions** button in the Activity Bar (or press `Cmd+Shift+X` on macOS / `Ctrl+Shift+X` on Windows/Linux).

    ![VS Code Extensions](images/vscode-extensions.png)

2. Look for **evo-mcp** in the list of **MCP Servers - Installed**.

    ![VS Code MCP Servers](images/vscode-mcp-servers.png)

3. Ensure there are no warning icons or error messages displayed.

If you see **evo-mcp** listed without any warnings, the configuration is correct and the server is ready to use.

### Cursor

#### Installation

Cursor is an AI-powered code editor with built-in support for MCP servers. To use the Evo MCP server in Cursor first [download and install it](https://cursor.com/download). 
NOTE: Cursor requires a paid subscription to use MCP features.

#### Configuration

Run the supplied Python script to add the required settings. The script will ask you a series of questions in the console.

**If you set up Python with `uv`:**
```bash
uv run python scripts/setup_mcp.py
```

**If you set up Python with `pip`:**
```bash
python scripts/setup_mcp.py
```

#### Manual method
1. Copy the settings found in `templates/cursor-stdio-config.json`.
  - For HTTP mode, use `templates/cursor-http-config.json` instead.
  - Update the template URL host and port to match `MCP_HTTP_HOST` and `MCP_HTTP_PORT` in your `.env`, and ensure the HTTP server is running.
2. Open the **Command Palette** (press `Cmd+Shift+P` on macOS / `Ctrl+Shift+P` on Windows/Linux).
3. Search for "mcp". Select **View: Open MCP Settings** to update the user settings.
  ![Cursor Command Palette](images/cursor-command-palette.png)

4. Click the **Add Custom MCP** button.

    ![Cursor MCP Add New Settings](images/cursor-mcp-add-new.png)

5. Paste the settings you copied from the template, update the paths to match your local installation, and save the file. NOTE: The JSON template shows Windows file paths but the screenshot below shows macOS file paths. Follow the conventions that suit your operating system. 
  ![Cursor MCP Settings](images/cursor-settings.png)
6. The MCP server will start automatically when accessed by Cursor AI.

#### Verifying the integration

To verify that the Evo MCP server is correctly configured in Cursor:

1. Open **Settings > Cursor Settings**.
2. In the search bar, type **Tools & MCP**.
3. Look for **evo-mcp** in the **Installed MCP Servers** list. The MCP server should be enabled, display with a green light and list the properties of the server, eg. number of tools, etc.
  ![Cursor Verify Settings](images/cursor-verify-settings.png)


### Additional tips

- **Use a separate workspace**: Create a new workspace that is separate to your clone of this repository. If your copilot/agent has access to the source files in this repository, it may decide to ignore the MCP server.
- **STDIO mode starts on demand**: In `STDIO` mode, VS Code/Cursor will launch the MCP server when needed.
- **HTTP mode needs a running server**: If you select `HTTP`, the server must already be running. The setup script can start it for you in the current terminal session so you can see live output.
- **Check your environment variables**: Ensure `EVO_CLIENT_ID` and `EVO_REDIRECT_URL` are set in your `.env` file before connecting.
    
- **`invalid_token` errors in delegated mode**: If you see `"error": "invalid_token"` after the server times out waiting for authentication, the client likely holds stale tokens from a previous registration. **Resolution:** Clear your MCP client's saved tokens/credentials for this server and reconnect — the client will re-register via DCR and obtain fresh tokens. Also verify that the redirect URI registered in your IMS application matches `{MCP_PUBLIC_BASE_URL}/signin-callback` (or your custom `OIDCPROXY_REDIRECT_PATH`). Another possible cause is the Oauth provider is temporarily unavailable or there is a network issue. If the problem persists, check  [Bentley Status Page](https://status.bentley.com/) for more details or contact support.
- **Reload after changes**: If you edit settings or `.env` values, reload the window so the client picks up the new config.

---

## Advanced

### Testing with FastMCP CLI

Running Evo MCP in streamable HTTP mode allows you to use the `fastmcp` CLI to access MCP tools without manually crafting JSON-RPC payloads.

**Setup:**
```bash
# In .env or environment
MCP_TRANSPORT=HTTP
MCP_HTTP_HOST=localhost
MCP_HTTP_PORT=5000
```

**Start the server:**

If you ran `setup_mcp.py`, selected `HTTP`, and chose to start now, the script starts the server in the current terminal so you can see live logs.

Otherwise, start it manually:
```bash
python src/mcp_tools.py
```

The server will start listening on `http://localhost:5000/mcp`.

**Access tools using FastMCP CLI:**

If you installed with `uv`, run these commands as `uv run fastmcp ...`. If you installed into an active virtual environment with `pip install -e .`, run `fastmcp ...` directly instead.

For simple arguments, prefer `key=value` parameters; use `--input-json` for more complex or nested inputs.

```bash
# Use either `uv run fastmcp ...` or `fastmcp ...`, depending on your installation method.

# 1) List available tools on the server
uv run fastmcp list http://localhost:5000/mcp --transport http

# 2) List workspaces
uv run fastmcp call http://localhost:5000/mcp list_workspaces \
  --transport http \
  name="" \
  deleted=false \
  limit=50 \
  --json

# 3) Create a workspace
uv run fastmcp call http://localhost:5000/mcp create_workspace \
  --transport http \
  name="My New Workspace" \
  description="Test workspace" \
  --json
```

> Note: The FastMCP CLI handles MCP session setup automatically, so no manual `initialize` request or `Mcp-Session-Id` header handling is required.

### Testing with a Google ADK agent

An example Google ADK agent is provided for testing the MCP server:

**Prerequisites**
- Google Cloud SDK (`gcloud` CLI) installed and configured

  ```powershell
  gcloud auth application-default login
  ```

- A GCP project with Vertex AI API enabled

**Add to `.env`**

```bash
GOOGLE_CLOUD_PROJECT=your-project-id
GOOGLE_CLOUD_LOCATION=your-region

# Passed through to the MCP server's `MCP_TOOL_FILTER` config.
MCP_TOOL_FILTER=all
```

**Run**
  ```powershell
  cd src\agents
  adk web
  ```

Browse to http://localhost:8000 to interact with the agent.

## Development

To add new MCP tools:
1. Add tool function to appropriate module in `src/evo_mcp/tools/`
2. Decorate with `@mcp.tool()` decorator
3. Tools are auto-registered based on their module (general/admin/data) on server startup
4. Test using VS Code integration or the ADK agent

### Linting

This repository uses Ruff for linting and formatting checks.
Linting also verifies that Python files include the required SPDX license header.

Run lint checks:

```bash
make lint
```

Auto-fix lint and formatting issues:

```bash
make lint-fix
```

### Pre-commit

Install pre-commit hooks:

The local pre-commit hook will also auto-insert missing SPDX headers in Python files.

```bash
uv run --extra dev pre-commit install
```

Run hooks on all files:

```bash
uv run --extra dev pre-commit run --all-files
```

## Contributing

Thank you for your interest in contributing to Seequent software. Please have a look over our [contribution guide.](./CONTRIBUTING.md)

## Code of conduct

We rely on an open, friendly, inclusive environment. To help us ensure this remains possible, please familiarise yourself with our [code of conduct](./CODE_OF_CONDUCT.md).

## License

The Evo MCP server is open source and licensed under the [Apache 2.0 license](./LICENSE.md).

Copyright © 2026 Bentley Systems, Incorporated.

Licensed under the Apache License, Version 2.0 (the "License").
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

## Disclaimer

Before using an MCP Server, you should consider conducting your own independent assessment to ensure that your use would comply with your own specific security and quality control practices and standards, as well as the laws, rules, and regulations that govern you and your content.

## Acknowledgements

Much of this document was inspired by the excellent guides written by [FastMCP](https://gofastmcp.com) and [AWS Labs](https://github.com/awslabs/mcp).
