Skip to main content

Flask Extension for apcore AI-Perceivable Core integration, exposes Flask routes as MCP tools with auto-discovery, schema inference, YAML binding, and built-in observability. Supports MCP server (stdio/HTTP) for LLM tool integration.

Project description

flask-apcore

Flask Extension for apcore (AI-Perceivable Core) integration. Expose your Flask routes as MCP tools with auto-discovery, Pydantic schema inference, and built-in observability.

Features

  • Route scanning -- auto-discover Flask routes and convert them to apcore modules
  • Annotation inference -- GET -> readonly, DELETE -> destructive, PUT -> idempotent
  • Pydantic schema inference -- input/output schemas extracted from type hints automatically
  • @module decorator -- define standalone AI-callable modules with full schema enforcement
  • YAML binding -- zero-code module definitions via external .binding.yaml files
  • MCP server -- stdio and streamable-http transports via flask apcore serve
  • Observability -- distributed tracing, metrics, and structured JSON logging
  • Input validation -- validate tool inputs against Pydantic schemas before execution
  • CLI-first workflow -- flask apcore scan + flask apcore serve for zero-intrusion integration
  • MCP Tool Explorer -- browser UI for inspecting modules via flask apcore serve --explorer

Requirements

  • Python >= 3.11
  • Flask >= 3.0

Installation

# Core
pip install flask-apcore

# With MCP server support (required for `flask apcore serve`)
pip install flask-apcore[mcp]

# All optional extras
pip install flask-apcore[mcp,smorest,restx]

Quick Start

1. Add Apcore to your Flask app

from flask import Flask
from flask_apcore import Apcore

app = Flask(__name__)
Apcore(app)

@app.route("/greet/<name>", methods=["GET"])
def greet(name: str) -> dict:
    """Greet a user by name."""
    return {"message": f"Hello, {name}!"}

Or use the factory pattern:

from flask import Flask
from flask_apcore import Apcore

apcore = Apcore()

def create_app():
    app = Flask(__name__)
    # ... register routes / blueprints ...
    apcore.init_app(app)
    return app

2. Scan routes and start MCP server

export FLASK_APP=app.py

# Scan Flask routes -> register as apcore modules
flask apcore scan

# Start MCP server (stdio, for Claude Desktop / Cursor)
flask apcore serve

That's it. Your Flask routes are now MCP tools.

3. Connect an MCP client

For Claude Desktop, add to your config:

{
  "mcpServers": {
    "my-flask-app": {
      "command": "flask",
      "args": ["apcore", "serve"],
      "env": { "FLASK_APP": "app.py" }
    }
  }
}

For HTTP transport (remote access):

flask apcore serve --http --host 0.0.0.0 --port 9100

Integration Paths

flask-apcore supports three ways to define AI-perceivable modules:

Route Scanning (zero-intrusion)

Scan existing Flask routes without modifying any code:

# Direct registration (in-memory)
flask apcore scan

# Generate YAML binding files (persistent)
flask apcore scan --output yaml --dir ./apcore_modules

# Preview without side effects
flask apcore scan --dry-run

# Filter routes by regex
flask apcore scan --include "user.*" --exclude ".*delete"

@module Decorator (precise control)

Define standalone modules with full schema enforcement:

from flask_apcore import Apcore, module
from pydantic import BaseModel

class SummaryResult(BaseModel):
    total: int
    active: int

@module(id="user_stats.v1", tags=["analytics"])
def user_stats() -> SummaryResult:
    """Return user statistics."""
    return SummaryResult(total=100, active=42)

app = Flask(__name__)
app.config["APCORE_MODULE_PACKAGES"] = ["myapp.modules"]
Apcore(app)

YAML Binding (zero-code)

Define modules externally in .binding.yaml files:

# apcore_modules/greet.binding.yaml
bindings:
  - module_id: greet.get
    target: app.greet
    description: "Greet a user by name"

Set APCORE_AUTO_DISCOVER=True (default) to load bindings on startup.

CLI Commands

flask apcore scan

Scan Flask routes and generate apcore module definitions.

Options:
  -s, --source [auto|native|smorest|restx]  Scanner source (default: auto)
  -o, --output [yaml]                       Output format; omit for direct registration
  -d, --dir PATH                            Output directory (default: APCORE_MODULE_DIR)
  --dry-run                                 Preview without writing or registering
  --include REGEX                           Only include matching module IDs
  --exclude REGEX                           Exclude matching module IDs

flask apcore serve

Start an MCP server exposing registered modules as tools.

Options:
  --stdio                  Use stdio transport (default)
  --http                   Use streamable-http transport
  --host TEXT              HTTP host (default: 127.0.0.1)
  -p, --port INT           HTTP port (default: 9100)
  --name TEXT              MCP server name (default: apcore-mcp)
  --validate-inputs        Validate tool inputs against schemas
  --log-level [DEBUG|INFO|WARNING|ERROR]
  --explorer               Enable the MCP Tool Explorer UI
  --explorer-prefix TEXT   URL prefix for explorer (default: /explorer)
  --allow-execute          Allow Try-it execution in the explorer

Configuration

All settings use the APCORE_ prefix in app.config:

app.config.update(
    # Core
    APCORE_AUTO_DISCOVER=True,          # Auto-load bindings and @module packages
    APCORE_MODULE_DIR="apcore_modules/",# Directory for binding files
    APCORE_BINDING_PATTERN="*.binding.yaml",  # Glob pattern for binding files
    APCORE_MODULE_PACKAGES=[],          # Python packages to scan for @module functions
    APCORE_SCANNER_SOURCE="auto",       # Scanner: auto, native, smorest, restx

    # Middleware & Execution
    APCORE_MIDDLEWARES=[],              # Middleware dotted paths (e.g. ["myapp.mw.AuthMW"])
    APCORE_ACL_PATH=None,              # ACL file path (e.g. "acl.yaml")
    APCORE_CONTEXT_FACTORY=None,       # Custom ContextFactory dotted path
    APCORE_EXECUTOR_CONFIG=None,       # Executor config dict (passed to apcore.Config)
    APCORE_EXTENSIONS=[],              # Extension plugin dotted paths

    # MCP Server
    APCORE_SERVE_TRANSPORT="stdio",     # Transport: stdio, streamable-http, sse
    APCORE_SERVE_HOST="127.0.0.1",      # HTTP host
    APCORE_SERVE_PORT=9100,             # HTTP port
    APCORE_SERVER_NAME="apcore-mcp",    # MCP server name
    APCORE_SERVER_VERSION=None,         # MCP server version string
    APCORE_SERVE_VALIDATE_INPUTS=False, # Validate inputs against schemas
    APCORE_SERVE_LOG_LEVEL=None,        # Log level: DEBUG, INFO, WARNING, ERROR

    # Observability
    APCORE_TRACING_ENABLED=False,       # Enable distributed tracing
    APCORE_TRACING_EXPORTER="stdout",   # Exporter: stdout, memory, otlp
    APCORE_TRACING_OTLP_ENDPOINT=None,  # OTLP collector URL (e.g. "http://localhost:4317")
    APCORE_TRACING_SERVICE_NAME="flask-apcore",  # Service name for traces
    APCORE_METRICS_ENABLED=False,       # Enable metrics collection
    APCORE_METRICS_BUCKETS=None,        # Custom histogram buckets (list of floats)
    APCORE_LOGGING_ENABLED=False,       # Enable structured logging
    APCORE_LOGGING_FORMAT="json",       # Format: json, text
    APCORE_LOGGING_LEVEL="INFO",        # Level: trace, debug, info, warn, error, fatal

    # MCP Serve Explorer (dev/staging only — no built-in auth)
    APCORE_SERVE_EXPLORER=False,             # Enable Tool Explorer UI in MCP server
    APCORE_SERVE_EXPLORER_PREFIX="/explorer", # URL prefix for explorer
    APCORE_SERVE_ALLOW_EXECUTE=False,        # Allow Try-it execution in explorer
)

Observability

Enable tracing, metrics, and structured logging:

app.config.update(
    APCORE_TRACING_ENABLED=True,
    APCORE_TRACING_EXPORTER="otlp",
    APCORE_TRACING_OTLP_ENDPOINT="http://localhost:4317",
    APCORE_METRICS_ENABLED=True,
    APCORE_LOGGING_ENABLED=True,
    APCORE_LOGGING_FORMAT="json",
)

These are wired into the apcore Executor as middleware, providing tracing spans, latency metrics, and structured log entries for every module execution.

MCP Tool Explorer

The MCP Tool Explorer is a browser UI provided by apcore-mcp for inspecting registered modules and executing them interactively.

Security: Explorer endpoints are unauthenticated. Only enable in development/staging. Do NOT enable in production without adding your own auth layer.

flask apcore serve --http --explorer --allow-execute

Browse to http://127.0.0.1:9100/explorer/ to view the interactive explorer with Try-it execution.

Docker Demo

A complete runnable demo is included in examples/demo/. It demonstrates the full pipeline: Flask CRUD routes with Pydantic schemas, route scanning, annotation inference, @module registration, MCP server, and observability.

cd examples/demo
docker compose up --build

After startup you'll see:

=== Scanning Flask routes ===
[flask-apcore] Found 5 API routes.
[flask-apcore] Generated 5 module definitions.

=== Starting MCP server on port 9100 ===
[flask-apcore] Starting MCP server 'task-manager-mcp' via streamable-http...
[flask-apcore] 6 modules registered.
INFO:     Uvicorn running on http://0.0.0.0:9100

Verify:

curl http://localhost:9100/health
# {"status":"ok","uptime_seconds":5.2,"module_count":6}

See examples/demo/README.md for full details.

Public API

from flask_apcore import (
    Apcore,             # Flask Extension
    module,             # @module decorator
    Registry,           # Module registry
    Executor,           # Module executor with middleware pipeline
    Context,            # Request context
    Identity,           # User identity
    ACL,                # Access control list
    Config,             # Executor configuration
    Middleware,          # Middleware base class
    ModuleAnnotations,  # Behavioral hints (readonly, destructive, etc.)
    ModuleDescriptor,   # Module metadata
)

Development

git clone https://github.com/aipartnerup/flask-apcore.git
cd flask-apcore
pip install -e ".[dev,mcp]"
pytest

License

Apache-2.0

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

flask_apcore-0.2.1.tar.gz (141.5 kB view details)

Uploaded Source

Built Distribution

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

flask_apcore-0.2.1-py3-none-any.whl (39.7 kB view details)

Uploaded Python 3

File details

Details for the file flask_apcore-0.2.1.tar.gz.

File metadata

  • Download URL: flask_apcore-0.2.1.tar.gz
  • Upload date:
  • Size: 141.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for flask_apcore-0.2.1.tar.gz
Algorithm Hash digest
SHA256 398064478023a8972f85772b650d3662f97e971b0a2ffd738ae78648facc2e85
MD5 6023283d235e3b7dff840e1dfea825c8
BLAKE2b-256 23da1a299f651c52691e8105fa164bafcc15b4a32985cdb37c05c5a69a26d71f

See more details on using hashes here.

File details

Details for the file flask_apcore-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: flask_apcore-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 39.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for flask_apcore-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 189ba3a37ed8527fab4948748d02b9a3c1dd2ef7cef3919349f2d53e7d63a5a5
MD5 bf394f07bfeb7c153c4e8f93ec22ae61
BLAKE2b-256 25c3577568e86a68eeff965db05d86ea202c14434e795befec5d174c69a6c434

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