Skip to main content

Enterprise golden-path framework for scaffolding MCP-first agent servers in Python.

Project description

agent-easy

Scaffold production-ready MCP servers in Python — without inventing the plumbing.

You want agents to call your tools over the Model Context Protocol (MCP). You do not want to wire up transports, config, secrets, auth, health checks, and lint gates from scratch every time.

This framework generates a complete, typed, testable MCP server project you own. Run one command, configure YAML profiles, add your tools, ship.

PyPI package: agent-easy-framework · CLI: agent-easy (pip install agent-easy-framework, then agent-easy mcp …)

You do not import this as a library at runtime. It is a generator (like JHipster or npx create-*). The output is a standalone repo your team maintains.


Quickstart (no clone)

uvx agent-easy-framework mcp my-service
cd my-service && make setup && make example

That scaffolds a stdio MCP server with a sample ping tool and runs it in-process (~5 seconds). Attach an MCP client with make run when ready.

Add another tool endpoint:

cd my-service
uvx agent-easy-framework mcp add-tool echo_reply
make check

Or from the project Makefile (same command, requires network):

cd my-service
make add-tool TOOL=echo_reply
make check

Full options:

uvx agent-easy-framework mcp billing-agent \
  --datasources postgres,neo4j \
  --transports stdio,http \
  --auth oidc

Locked-down environments (no uvx):

pip install agent-easy-framework
agent-easy mcp billing-agent --datasources neo4j --auth oidc

At a glance

What it generates An MCP-first Python server with tools, data sources, auth, and ops endpoints
Who it is for Engineers shipping agent tools to Claude Desktop, IDEs, or internal platforms
Config model YAML profiles (Spring-style). No environment variables
Quality bar mypy --strict, ruff, dead-code detection, golden-path fact-checks baked in
Deep reference GOLDEN_PATH.md — the contract every generated server follows
Copy-paste examples examples/README.md — call ping, curl ops, browse live docs

Try it now (reference server)

For contributors or anyone exploring the generator source, clone this repo:

make setup
make example          # Flow 1: ping in-process — no server (~5 seconds)

Call the tool over HTTP MCP (two terminals):

make run-http         # terminal 1
make example-http     # terminal 2 — Streamable HTTP client, not curl
./examples/smoke_ops.sh   # optional: ops REST at :8080

Full walkthrough: examples/README.md.


Your journey (start to shipped)

Follow this path whether you are new to MCP or just do not want to rebuild the same skeleton again.

flowchart LR
  subgraph step1 [1. Generate]
    gen["uvx agent-easy-framework mcp …"]
  end
  subgraph step2 [2. Configure]
    yaml["YAML profiles + secrets"]
  end
  subgraph step3 [3. Run]
    run["make run / make docs"]
  end
  subgraph step4 [4. Extend]
    tools["Add @tool handlers"]
  end
  subgraph step5 [5. Ship]
    ci["make check + CI"]
  end
  gen --> yaml --> run --> tools --> ci
Step 1 — Generate your server

Pick only what you need. Unused providers and transports are pruned so dependencies stay minimal.

uvx agent-easy-framework mcp billing-agent \
  --datasources postgres,neo4j \
  --transports stdio,http \
  --auth oidc
Flag Options Default When to use
--output, -o directory path . Parent folder for the new project
--package Python identifier derived from name Override the import package name
--datasources postgres, neo4j none Your tools need a database
--transports stdio, http, grpc stdio stdio = local/IDE; http = deployed; grpc = custom adapter
--auth none, oidc, basic none oidc for SSO in prod; basic is testing only (runtime API key)
--profile any name local Default active profile in config/base.yaml

Add a tool to an existing project

Run from the project root (or pass -C). Requires uvx and the published agent-easy-framework package:

cd my-service
uvx agent-easy-framework mcp add-tool echo_reply
uvx agent-easy-framework mcp add-tool send_invoice -d "Create and send a customer invoice."
make check

Or use the Makefile wrapper:

make add-tool TOOL=echo_reply
make check

Profile note: make run uses the active profile (local by default). The local profile forces stdio + no auth. Use PROFILE=prod or make run-http for HTTP/OIDC settings from generate flags.

Locked-down environments (no uvx):

pip install agent-easy-framework
agent-easy mcp billing-agent --datasources neo4j --auth oidc
Step 2 — Configure profiles and secrets

Generated layout:

billing-agent/
  config/
    base.yaml              # shared defaults + active_profile
    profiles/
      local.yaml           # deep-merged on top of base
      prod.yaml
  secrets/                 # file-based secret provider (gitignored)
    neo4j/password

Profiles — Spring-style. One knob at runtime:

billing-agent run                  # uses active_profile from base.yaml
billing-agent run --profile prod   # override

Secrets — never committed as raw values. Reference them in YAML:

password: ${secret:neo4j/password}

Create the file: secrets/neo4j/password (or plug in Vault / cloud providers later).

OIDC example (config/profiles/prod.yaml):

server:
  auth:
    provider: oidc
    options:
      issuer: https://login.your-idp.com/
      audience: billing-agent
      jwks_uri: https://login.your-idp.com/.well-known/jwks.json
Step 3 — Install and run
cd billing-agent
make setup          # venv + minimal deps for your selection
make run            # serve with default profile
make run PROFILE=prod
make docs           # live docs site from your tool registry (nothing committed)

Ops endpoints (for load balancers / k8s) — default 127.0.0.1:8080:

Endpoint Purpose
GET /health Liveness — process is up
GET /ready Readiness — all data sources healthy
GET /admin/tools Registered tools and descriptions

Other default ports:

Surface Default Notes
MCP (HTTP) 8000 at /mcp Streamable HTTP when --transports http
Live docs 8090 make docs — registry-generated, not committed
Step 4 — Add your tools

A tool is an async function with a typed Pydantic input model. The docstring becomes the MCP description.

Create src/billing_agent/core/tools/invoice.py (requires --datasources postgres in Step 1):

from pydantic import BaseModel, Field

from billing_agent.core.context import AppContext
from billing_agent.core.registry import tool


class LookupInput(BaseModel):
    invoice_id: str = Field(description="Invoice ID to fetch.")


class LookupOutput(BaseModel):
    total: float
    status: str


@tool
async def lookup_invoice(params: LookupInput, ctx: AppContext) -> LookupOutput:
    """Fetch an invoice total and status from the primary database."""
    db = ctx.datasource("primary")   # name from config/server.datasources
    rows = await db.fetch("SELECT total, status FROM invoices WHERE id = $1", params.invoice_id)
    row = rows[0]
    return LookupOutput(total=row["total"], status=row["status"])

Register it in src/billing_agent/core/tools/__init__.py:

from billing_agent.core.tools import invoice as invoice

Restart the server. Your tool appears in make docs and every transport automatically.

Step 5 — Verify and ship

Every generated project includes the same quality gates:

make check    # lint + type + deadcode + golden-path fact-checks
make test     # unit + smoke tests

CI in this repo runs the same checks on pull requests. Your generated project ships with pre-commit hooks ready to enable.


How a request flows

When an MCP client calls your server, everything funnels through one registry — transports are thin adapters.

sequenceDiagram
  participant Client as MCP Client
  participant Transport as Transport adapter
  participant Auth as Auth provider
  participant Registry as Tool registry
  participant Tool as Your @tool handler
  participant DS as Data source

  Client->>Transport: call_tool(name, arguments)
  alt HTTP or gRPC
    Transport->>Auth: validate Bearer token
    Auth-->>Transport: Principal
  end
  Transport->>Registry: invoke_tool(name, args)
  Registry->>Tool: handler(params, ctx)
  Tool->>DS: query (optional)
  DS-->>Tool: result
  Tool-->>Registry: Pydantic output
  Registry-->>Transport: JSON payload
  Transport-->>Client: MCP response

stdio skips auth (trusted local channel). HTTP and gRPC enforce the configured provider.


Architecture inside your generated server

One core, multiple ways in. You write tools once; every transport exposes them.

flowchart TB
  subgraph adapters [Transport adapters]
    stdio[stdio]
    http["Streamable HTTP"]
    grpc[gRPC adapter]
  end
  subgraph ops [FastAPI surfaces]
    health["/health · /ready · /admin"]
    docs["Live docs server"]
  end
  subgraph core [Transport-agnostic core]
    tools[Tool registry]
    ds[Data source registry]
    ctx[AppContext]
  end
  subgraph cfg [Config layer]
    yaml[YAML profiles]
    sec[Secret providers]
    auth[Auth providers]
  end
  stdio --> core
  http --> core
  grpc --> core
  ops --> core
  core --> cfg
  ds --> postgres[(PostgreSQL)]
  ds --> neo4j[(Neo4j)]

FastAPI powers ops endpoints and the live docs server (make docs). MCP traffic uses the official mcp SDK (stdio) or Starlette (Streamable HTTP). gRPC is a custom adapter over the same tool registry.


Choose your stack (decision guide)

flowchart TD
  start([I need an MCP server]) --> local{Local dev only?}
  local -->|Yes| stdio["transports: stdio"]
  local -->|No| http["transports: stdio,http"]
  http --> db{Need a database?}
  db -->|Postgres| pg["--datasources postgres"]
  db -->|Graph| neo["--datasources neo4j"]
  db -->|Both| both["--datasources postgres,neo4j"]
  db -->|No| none["--datasources omitted"]
  http --> auth{Production auth?}
  auth -->|SSO| oidc["--auth oidc"]
  auth -->|Quick local test| noneAuth["--auth none"]
  auth -->|Never prod| basic["--auth basic · testing only"]
  stdio --> done([make setup && make run])
  pg --> done
  neo --> done
  both --> done
  none --> done
  oidc --> done
  noneAuth --> done
  basic --> done

Example: Neo4j + OIDC (production-shaped)

uvx agent-easy-framework mcp graph-agent \
  --datasources neo4j \
  --transports stdio,http \
  --auth oidc
cd graph-agent
mkdir -p secrets/neo4j
echo 'your-password' > secrets/neo4j/password
make setup && make run PROFILE=prod

Point config/profiles/prod.yaml at your IdP and Neo4j bolt URI. HTTP clients send Authorization: Bearer <jwt>.


What you get out of the box

  • MCP-first — official mcp SDK; tools registered via @tool with enforced typing and docstrings
  • Minimal deps — generator prunes what you did not select
  • YAML profiles — no environment variables; --profile CLI override
  • Pluggable providers — same pattern for secrets, auth, and data sources
  • Live docsmake docs serves a registry-generated site; nothing committed
  • Quality gates — ruff, mypy --strict, vulture, custom fact-checks, pytest smoke test

Generated project commands

Command What it does
make setup Create venv, install deps
make example Call ping in-process (fast validation, no server)
make run Run server (PROFILE=prod to override)
make run-http Run HTTP MCP transport (when generated with --transports http)
make example-http Call ping over HTTP MCP (when generated with --transports http)
make docs Serve live documentation
make check Lint + type + deadcode + golden-path fact-checks
make factcheck Golden-path invariants only
make test Run tests
make fmt Auto-format
make all check + test

Contributing to this framework

For maintainers working on the generator itself:

git clone https://github.com/KazzyAPI/agent-easy.git
cd agent-easy
make setup          # sync templates + venv + dev deps
make check && make test
make sync-templates # refresh bundled templates before publishing

See GOLDEN_PATH.md for the full architectural contract.


License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

agent_easy_framework-0.0.4.tar.gz (160.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

agent_easy_framework-0.0.4-py3-none-any.whl (72.6 kB view details)

Uploaded Python 3

File details

Details for the file agent_easy_framework-0.0.4.tar.gz.

File metadata

  • Download URL: agent_easy_framework-0.0.4.tar.gz
  • Upload date:
  • Size: 160.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for agent_easy_framework-0.0.4.tar.gz
Algorithm Hash digest
SHA256 c1b4c383f5e0f429c9a9b5fce619758eed1e49834b8a8c7b68ae97bba2abbc1d
MD5 eef1a3bea49587353e7aecccdd33e4ed
BLAKE2b-256 cd842a517f336ac6543c7a21e3969e229e7a32adebf593049ed1f931ee9e5ae5

See more details on using hashes here.

File details

Details for the file agent_easy_framework-0.0.4-py3-none-any.whl.

File metadata

File hashes

Hashes for agent_easy_framework-0.0.4-py3-none-any.whl
Algorithm Hash digest
SHA256 61d0e55cde1a451f6a5c81908ec3b1e5ae814682f755d37f47e30133ce6b13b2
MD5 8e1abad0abed4888d20621b1198a320e
BLAKE2b-256 7c9bf45cc9cda6169456ff41218f9410bd8c857a09380e17ae9f4ee67ebde70e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page