Skip to main content

Unified Nexus

Unified Nexus is a high-performance Python framework that bridges the gap between traditional REST APIs and the new world of LLM-native tools (MCP). Build product-grade backends where your web frontend and AI agents share the exact same logic, schemas, and execution paths — defined once.


The Problem

In a traditional stack, you define a FastAPI route, then manually re-wrap it as an MCP tool. Over time, these two definitions drift apart — different validation, different schemas, different behavior. This is Code Drift, and it silently breaks your AI integrations.

❌ Traditional Stack
├── routes/user.py       ← HTTP logic
├── mcp_tools/user.py    ← Copy-pasted MCP logic (already out of sync)
└── models/user.py       ← Shared? Maybe. Hopefully.
✅ Unified Nexus
└── main.py              ← One function. One decorator. Both interfaces. Always in sync.

Installation

git clone <git rep>

Quick Start

from UnifiedNexus.unified_nexus import UnifiedNexus
from pydantic import BaseModel, Field

nexus = UnifiedNexus("MyNexusAPI")

class UserRequest(BaseModel):
    user_id: int = Field(..., description="The unique ID of the user")

@nexus.universal_tool(path="/user-info")
def get_user(req: UserRequest):
    """
    Fetches user status and clearance level.
    This docstring is used by both Swagger UI and AI Agents automatically.
    """
    return {"id": req.user_id, "status": "Active", "tier": "Gold"}

app = nexus.finalize()

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)

Run it:

python main.py
Interface URL
REST API Docs (Swagger) http://localhost:8000/docs
MCP SSE Endpoint http://localhost:8000/mcp
MCP Inspector npx -y @modelcontextprotocol/inspector http://localhost:8000/mcp

Core Features

Single Source of Truth

Define your function once. Unified Nexus simultaneously registers it as a FastAPI route and an MCP tool. Validation, schemas, and business logic are identical for HTTP clients and AI agents — no drift, no duplication.

Auto-Method Detection

Unified Nexus intelligently selects GET or POST based on your function signature. Functions with a Pydantic model input default to POST; pure query-based functions use GET. No configuration needed.

AI-Native Tool Descriptions

Your Python docstrings become rich, structured tool descriptions for MCP hosts like Claude, Cursor, and Copilot. Descriptive Field(description=...) annotations on your Pydantic models are passed directly to the LLM — helping it understand how to call your tools correctly.

Shared Middleware

Apply authentication, rate limiting, or logging once at the UnifiedNexus level. The same middleware protects both your HTTP API and your MCP interface — no configuration duplication.

LLM-Optimized Errors

When your tool raises a Python exception, Unified Nexus converts it into a structured natural-language hint that helps LLMs self-correct their tool calls — rather than returning a raw stack trace the model cannot act on.

Lifespan-Safe MCP Integration

The finalize() method correctly composes FastAPI and FastMCP lifespans, ensuring the MCP StreamableHTTPSessionManager task group is always initialized before requests arrive. No runtime errors, no manual wiring.


Architecture

Your Code (@universal_tool)
        │
        ▼
  UnifiedNexus.finalize()
     ┌──────┴──────┐
     │             │
  FastAPI        FastMCP
  /docs           /mcp
  REST           SSE/MCP
     │             │
     └──────┬──────┘
            │
      Single ASGI App
      (Uvicorn / any ASGI server)

Advanced Usage

Custom Path and Methods

@nexus.universal_tool(path="/search", methods=["GET"])
def search_items(query: str, limit: int = 10):
    """Search the item catalog. Returns a ranked list of results."""
    return {"results": [...], "total": 42}

Shared Auth Middleware

from unified_nexus.middleware import BearerAuthMiddleware

nexus = UnifiedNexus("SecureAPI")
nexus.add_middleware(BearerAuthMiddleware, token="your-secret-token")

Async Support

@nexus.universal_tool(path="/fetch-data")
async def fetch_external(resource_id: str):
    """Fetches data from an external source asynchronously."""
    async with httpx.AsyncClient() as client:
        response = await client.get(f"https://api.example.com/{resource_id}")
    return response.json()

Exposure Control: API Only, MCP Only, or Both

Control interface exposure at both the application level and individual tool level.

1. Server-Level Control

Set the exposure mode during initialization or when calling finalize():

# Option A: Both REST API and MCP (default)
nexus = UnifiedNexus("MyApp", expose="both")

# Option B: REST API Only (disables MCP endpoint and lifespan)
nexus = UnifiedNexus("MyApp", expose="api")

# Option C: MCP Only (disables REST API routes and Swagger docs)
nexus = UnifiedNexus("MyApp", expose="mcp")

# Override at finalization if desired:
app = nexus.finalize(expose="api")  # or expose="mcp", expose="both"
Mode REST Routes (/docs) MCP Endpoint (/mcp)
"both" ✅ Active ✅ Active
"api" ✅ Active ❌ Disabled (404)
"mcp" ❌ Disabled (404) ✅ Active

2. Tool-Level Control

Decide which interfaces expose specific functions:

# Expose ONLY to REST API
@nexus.universal_tool(path="/web-dashboard", expose="api")
def web_only_data():
    return {"status": "ok"}

# Or use the shortcut decorator:
@nexus.api_only("/metrics")
def get_metrics():
    return {"cpu": 12}

# Expose ONLY to MCP AI Agents (path is optional!)
@nexus.universal_tool(expose="mcp")
def query_vector_store(query: str):
    return {"results": [...]}

# Or use the shortcut decorator:
@nexus.mcp_only
def plan_agent_task(step: str):
    return {"step": step}

# Expose to BOTH REST and MCP (default)
@nexus.universal_tool(path="/shared-tool", expose="both")
def shared_tool():
    return {"shared": True}

Industry-Standard Microservice Integration (Mounting to Existing FastAPI Apps)

In real-world microservice architectures, you already have an existing FastAPI application with database pools, telemetry, auth dependencies (Depends), and custom lifespans. UnifiedNexus can be mounted directly onto your existing app:

from fastapi import FastAPI, APIRouter, Depends
from unified_nexus import UnifiedNexus

# 1. Your existing microservice application with custom lifespan
app = FastAPI(title="PaymentMicroservice", version="2.0.0")

# 2. Initialize UnifiedNexus
nexus = UnifiedNexus("PaymentNexus")

# Database dependency (FastAPI Depends is automatically resolved in MCP tool calls!)
def get_db():
    return "session_postgres"

# Fine-grained endpoint control:
@nexus.universal_tool(path="/charge", expose="both")
def charge_card(amount: float, db: str = Depends(get_db)):
    """Exposed to both HTTP REST clients and AI Agents."""
    return {"status": "paid", "amount": amount}

@nexus.api_only(path="/internal-health")
def internal_health():
    """REST only — hidden from AI agents."""
    return {"status": "ok"}

@nexus.mcp_only
def fraud_analysis(account_id: str):
    """MCP only — accessible exclusively by AI agents."""
    return {"risk": "low"}

# Expose an existing microservice APIRouter to MCP:
billing_router = APIRouter()
@billing_router.get("/invoices")
def get_invoices():
    return {"invoices": []}

nexus.include_router(billing_router, prefix="/billing", expose="both")

# 3. Mount directly to your existing FastAPI microservice
nexus.attach_to(
    app,
    api_prefix="/api/v1",  # Prefixes REST routes: /api/v1/charge, /api/v1/billing/invoices
    mcp_path="/",          # MCP endpoint available at /mcp
    mode="both",           # 'both', 'api', or 'mcp'
)

# 4. Your existing ASGI server runs app unchanged:
# uvicorn.run(app, host="0.0.0.0", port=8000)

Key Microservice Features:

  • Lifespan Composition: Automatically chains your existing database/Kafka lifespans with FastMCP's task group.
  • Depends() Resolution: FastAPI dependencies in your endpoints are resolved automatically when invoked by AI agents via MCP.
  • Versioned API Prefixing: api_prefix="/api/v1" keeps your REST API versioned while FastMCP tools maintain clean operation names.
  • Full Router Interoperability: nexus.include_router(..., expose="both") instantly makes entire existing APIRouters accessible to AI tools.

LangServe & UnifiedNexus Collaboration (The Killer Advantage)

Modern AI backends typically require two communication layers:

  1. LangServe: Serves LangChain LCEL chains via HTTP (/invoke, /stream, /batch, interactive playground) for web and mobile frontends.
  2. UnifiedNexus (FastMCP): Serves native tool calling via Model Context Protocol (/mcp SSE) for autonomous AI agents (Claude, Cursor, Copilot, ChatGPT).

Mounting LangServe and UnifiedNexus together on a single FastAPI app solves the AI backend dilemma:

from fastapi import FastAPI
from langserve import add_routes
from langchain_core.runnables import RunnableLambda
from unified_nexus import UnifiedNexus

app = FastAPI(title="HybridAIPlatform")
nexus = UnifiedNexus("EnterpriseNexus")

# 1. LangChain LCEL Chain (served via LangServe)
def summarize_doc(data: dict):
    return {"summary": data["text"].upper()}

summary_chain = RunnableLambda(summarize_doc)
add_routes(app, summary_chain, path="/summarize")

# 2. UnifiedNexus Universal Tool (accessible via REST and MCP)
@nexus.universal_tool(path="/search", expose="both")
def search_knowledge_base(query: str):
    """Semantic document search tool."""
    return {"query": query, "results": ["Doc #1", "Doc #2"]}

# 3. FastMCP tool that invokes the LangChain chain in-process!
@nexus.mcp_only
async def agent_summarizer(content: str):
    """Summarizes text using the internal LCEL chain."""
    return await summary_chain.ainvoke({"text": content})

# 4. Attach UnifiedNexus to the same FastAPI app
nexus.attach_to(app, api_prefix="/api/v1", mcp_path="/")

# Run with: uvicorn app:app --port 8000

Why This Is Game-Changing:

  • Single Process, Single Port: Web frontends stream LCEL chains via LangServe, while AI agents call tools via MCP.
  • In-Process Chain Execution: MCP tools can invoke LangChain runnables directly without extra HTTP hops.
  • Zero Drift: Data schemas and business logic stay unified across both human users and AI agents.

Connecting AI Agents

Claude Desktop (claude_desktop_config.json)

{
  "mcpServers": {
    "my-nexus-api": {
      "url": "http://localhost:8000/mcp",
      "transport": "streamable-http"
    }
  }
}

Cursor / VS Code

Add http://localhost:8000/mcp as an MCP server in your editor's AI settings.

Verify with MCP Inspector

npx -y @modelcontextprotocol/inspector http://localhost:8000/mcp

📂 Feature Examples

The examples/ directory contains complete, runnable demonstrations for each feature:

Example Feature Highlight Command
01_quickstart.py Basic unified tool, auto GET/POST detection, Swagger & MCP python examples/01_quickstart.py
02_exposure_modes.py Exposure control (both, api, mcp), @api_only, @mcp_only python examples/02_exposure_modes.py
03_router_integration.py Modular APIRouter support & auto-exposing routers to MCP python examples/03_router_integration.py
04_middleware_and_security.py Shared CORS/timing middleware, LLM error recovery hints python examples/04_middleware_and_security.py
05_dependency_injection.py Automatic FastAPI Depends() resolution in MCP calls python examples/05_dependency_injection.py
06_microservice_mount.py Mounting to existing FastAPI apps, composed lifespans, /api/v1 python examples/06_microservice_mount.py
07_stdio_agent_server.py Stdio transport for local Claude Desktop CLI & Cursor python examples/07_stdio_agent_server.py
08_langserve_collaboration.py LangServe LCEL chain + FastMCP tools in the same FastAPI app python examples/08_langserve_collaboration.py
microservice_example.py Production customer order microservice with health probes python examples/microservice_example.py

🚀 Production Readiness & PyPI Publishing

UnifiedNexus is 100% production-ready:

  • ✅ Fully Typed (PEP 561): Includes py.typed marker for static typing (mypy, pyright).
  • ✅ Packaging: Standard PEP 621 / Hatchling configuration with clean wheel targets.
  • ✅ Automated Test Coverage: 24 tests covering edge cases, dependency injection, and lifespans.
  • ✅ Error Resilient: Converts unexpected exceptions into structured hints for LLMs.

Building & Publishing to PyPI

# 1. Build the distribution packages (.tar.gz and .whl)
uv build
# or: python -m build

# 2. Check the built packages
twine check dist/*

# 3. Publish to PyPI
twine upload dist/*
# or: uv publish

Testing

Run the comprehensive test suite across Python 3.11 and 3.12:

pytest tests -v

Requirements

  • Python 3.11+
  • FastAPI >= 0.115.0
  • FastMCP >= 2.0.0
  • Uvicorn >= 0.30.0
  • Pydantic >= 2.0.0

Contributing

Contributions are welcome! Please open an issue to discuss proposed changes before submitting a PR.

Metadata

Release files for unified-nexus 0.1.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for unified-nexus 0.1.3
File Size Uploaded Provenance
unified_nexus-0.1.3.tar.gz 35.8 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for unified-nexus 0.1.3
File Interpreter ABI Platform
unified_nexus-0.1.3-py3-none-any.whl Python 3 none any Details

Total release size: 52.8 kB

Release files / unified_nexus-0.1.3.tar.gz

Download URL unified_nexus-0.1.3.tar.gz
Size 35.8 kB
Tags Source
SHA-256 checksum
How to use checksums
9d2f2455ac0fd9219cd382272c859791256d0bf607fbf1ef80d726dc6d57afbb
BLAKE2b-256 checksum
How to use checksums
7af185e55c79a5b848dbb028fe1385bd6eb817b97a7359c000bffe35540f4a3f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.9

Release files / unified_nexus-0.1.3-py3-none-any.whl

Download URL unified_nexus-0.1.3-py3-none-any.whl
Size 17.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
78c813e1798946df1a013d5c35a90d91938b7583106ee25985737535604cb430
BLAKE2b-256 checksum
How to use checksums
1e1000e32305549c9e9a0f9d44454956dc57ece7b7ec23fb7b3623c03e91f243
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.9

Security for unified-nexus 0.1.3

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page