mcpengine 0.3.0
MCPEngine is a Model Context Protocol SDK built for Production
License: MIT
Requires Python: >=3.10
Keywords: git, mcp, mcpengine, llm, automation

# MCPEngine

**Production-Grade Implementation of the Model Context Protocol (MCP)**

<img src="assets/logo.png" alt="MCPEngine Logo" width="400">

## Overview

**MCPEngine** is a production-grade, HTTP-first implementation of the [Model Context Protocol (MCP)](https://modelcontextprotocol.io). It provides a secure, scalable, and modern framework for exposing data, tools, and prompts to Large Language Models (LLMs) via MCP.

We believe MCP can be the "**REST for LLMs**," enabling any application (Slack, Gmail, GitHub, etc.) to expose a standardized endpoint that LLMs can access without custom-coded integrations. **MCPEngine** is our contribution to making MCP robust enough for modern, cloud-native use cases.

## Key Features

- **Built-in OAuth** with Okta, Keycloak, Google SSO, etc.  
- **HTTP-first** design (SSE instead of just stdio)  
- **Scope-based Authorization** for tools, resources, and prompts  
- **Seamless bridging** for LLM hosts (like Claude Desktop) via a local proxy  
- **Full backwards-compatibility** with FastMCP and the official MCP SDK

## Architecture

MCPEngine uses a proxy-based architecture to integrate with LLM hosts like Claude Desktop:

```
┌───────────────┐     stdio     ┌─────────────────┐     HTTP/SSE     ┌───────────────┐
│  Claude Host  ├───────────────►  MCPProxy Local ├──────────────────► MCPEngine     │
│               │               │                 │                   │ Server        │
│               ◄───────────────┤ (runs locally) ◄──────────────────┬┤ (remote)      │
└───────────────┘               └─────────────────┘      OAuth 2.1   │└───────────────┘
                                                                     │
                                                        ┌────────────┴───────────┐
                                                        │ Identity Provider      │
                                                        │ (Okta, Keycloak, etc.) │
                                                        └────────────────────────┘
```

This architecture provides several advantages:

1. **Seamless integration** - Claude sees a local stdio-based process
2. **Security** - The proxy handles OAuth authentication flows
3. **Scalability** - The MCPEngine server can run anywhere (cloud, on-prem)
4. **Separation of concerns** - Authentication is handled independently from your business logic

## Installation

```bash
uv add "mcpengine[cli]"
# or
pip install "mcpengine[cli]"
```

Once installed, you can run the CLI tools:

```bash
mcpengine --help
```

## Quickstart

### Create a Server

```python
# server.py
from mcpengine import MCPEngine

mcp = MCPEngine("Demo")


@mcp.tool()
def add(a: int, b: int) -> int:
    return a + b


@mcp.resource("greeting://{name}")
def get_greeting(name: str) -> str:
    return f"Hello, {name}!"
```

### Claude Desktop Integration

If your server is at <http://localhost:8000>, you can start the proxy locally:

```bash
mcpengine proxy http://localhost:8000/sse
```

Claude Desktop sees a local stdio server, while the proxy handles any necessary OAuth or SSE traffic automatically.

## Core Concepts

### Authentication & Authorization

Enable OAuth and scopes:

```python
from mcpengine import MCPEngine, Context
from mcpengine.server.auth.providers.config import IdpConfig

mcp = MCPEngine(
    "SecureDemo",
    idp_config=IdpConfig(
        issuer_url="https://your-idp.example.com/realms/some-realm",
    ),
)


@mcp.auth(scopes=["calc:read"])
@mcp.tool()
def add(a: int, b: int, ctx: Context) -> int:
    ctx.info(f"User {ctx.user_id} with roles {ctx.roles} called add.")
    return a + b
```

Any attempt to call `add` requires the user to have `calc:read` scope. Without it, the server returns 401 Unauthorized, prompting a login flow if used via the proxy.

### Resources

`@mcp.resource("uri")`: Provide read-only context for LLMs, like a GET endpoint.

```python
from mcpengine import MCPEngine

mcp = MCPEngine("Demo")


@mcp.resource("config://app")
def get_config() -> str:
    return "Configuration Data"
```

### Tools

`@mcp.tool()`: LLM-invokable functions. They can have side effects or perform computations.

```python
from mcpengine import MCPEngine

mcp = MCPEngine("Demo")


@mcp.tool()
def send_email(to: str, body: str):
    return "Email Sent!"
```

### Prompts

`@mcp.prompt()`: Reusable conversation templates.

```python
from mcpengine import MCPEngine

mcp = MCPEngine("Demo")


@mcp.prompt()
def debug_prompt(error_msg: str):
    return f"Debug: {error_msg}"
```

### Images

Return images as first-class data:

```python
from mcpengine import MCPEngine, Image

mcp = MCPEngine("Demo")


@mcp.tool()
def thumbnail(path: str) -> Image:
    # ... function body omitted
    pass
```

### Context

Each request has a Context:

- `ctx.user_id`: Authenticated user id
- `ctx.user_name`: Authenticated user name
- `ctx.roles`: User scopes/roles
- `ctx.info(...)`: Logging
- `ctx.read_resource(...)`: Access other resources

## Example Implementations

### SQLite Explorer

```python
import sqlite3
from mcpengine import MCPEngine, Context
from mcpengine.server.auth.providers.config import IdpConfig

mcp = MCPEngine(
    "SQLiteExplorer",
    idp_config=IdpConfig(
        issuer_url="https://your-idp.example.com/realms/some-realm",
    ),
)


@mcp.auth(scopes=["database:read"])
@mcp.tool()
def query_db(sql: str, ctx: Context) -> str:
    conn = sqlite3.connect("data.db")
    try:
        rows = conn.execute(sql).fetchall()
        ctx.info(f"User {ctx.user.id} executed query: {sql}")
        return str(rows)
    except Exception as e:
        return f"Error: {str(e)}"
```

### Echo Server

```python
from mcpengine import MCPEngine

mcp = MCPEngine("Demo")


@mcp.resource("echo://{msg}")
def echo_resource(msg: str):
    return f"Resource echo: {msg}"


@mcp.tool()
def echo_tool(msg: str):
    return f"Tool echo: {msg}"
```

## Smack - Message Storage Example

<img src="assets/mcpengine-smack-demo.gif" alt="MCPEngine Smack Demo" width="100%">

Smack is a simple messaging service example with PostgreSQL storage that demonstrates MCPEngine's capabilities with OAuth 2.1 authentication.

### Quick Start

1. Start the service using Docker Compose:

```bash
git clone https://github.com/featureform/mcp-engine.git
cd mcp-engine/examples/servers/smack
docker-compose up --build
```

2. Using Claude Desktop

Configure Claude Desktop to use Smack:

Manually:

```bash
touch ~/Library/Application\ Support/Claude/claude_desktop_config.json
```

Add to the file:

```json
{
  "mcpServers": {
    "smack_mcp_server": {
      "command": "bash",
      "args": [
        "docker attach mcpengine_proxy || docker run --rm -i --net=host --name mcpengine_proxy featureformcom/mcpengine-proxy -host=http://localhost:8000 -debug -client_id=optional -client_secret=optional",
      ]
    }
  }
}
```

Via CLI:

```bash
mcpengine proxy http://localhost:8000
```

Smack provides two main tools:

- `list_messages()`: Retrieves all messages
- `post_message(message: str)`: Posts a new message

For more details, see the [Smack example code](https://github.com/featureform/mcp-engine/tree/main/examples/servers/smack).

## Roadmap

- Advanced Auth Flows
- Service Discovery
- Fine-Grained Authorization
- Observability & Telemetry
- Ongoing FastMCP Compatibility

## Contributing

We welcome feedback, issues, and pull requests. If you'd like to shape MCP's future, open an issue or propose changes on [GitHub](https://github.com/featureform/mcp-engine). We actively maintain MCPEngine to align with real-world enterprise needs.

## Community

Join our discussion on [Slack](https://join.slack.com/t/featureform-community/shared_invite/zt-xhqp2m4i-JOCaN1vRN2NDXSVif10aQg?mc_cid=80bdc03b3b&mc_eid=UNIQID) to share feedback, propose features, or collaborate.

## License

Licensed under the MIT License. See LICENSE for details.