Expose Backend

Your stack:

Goal

Turn a Python module into a remotely callable backend service using Graftcode Gateway - no frameworks, no REST routes, no OpenAPI specs needed.

What You'll See

  • Create a small Python module with public methods.
  • Host it through Graftcode Gateway using Docker.
  • Explore the exposed methods in Graftcode Vision - your service is now accessible from any app as a strongly-typed client.

Prerequisites

  • Docker installed and running
  • Python only if you run the PyPI consumer locally - Docker alone is enough to build and host the service

Step 1. Create a project folder

Create a new folder and initialize a Python project:

mkdir py-energy-service
cd py-energy-service

Step 2. Write a Python module with public methods

Create a file energy_price_calculator.py:

import random

class EnergyPriceCalculator:
    @staticmethod
    def get_price() -> int:        
        return random.randint(100, 104)

Create module meta data file pyproject.toml:

[project]
name = "energy-service"
version = "1.0.0"
requires-python = ">=3.8"
description = "Test module for local directory analysis"

This is a plain Python class - no decorators, no frameworks, no special annotations. Any public method you write here will automatically become available for remote consumption once hosted through Graftcode Gateway.

Step 3. Host it with Graftcode Gateway

Create a Dockerfile in the project root:

FROM python:3.13-bookworm

WORKDIR /usr/app

COPY ./energy_price_calculator.py /usr/app/energy-service/
COPY ./pyproject.toml /usr/app/energy-service/

RUN apt-get update \
 && apt-get install -y wget \
 && wget -O /usr/app/gg.deb https://github.com/grft-dev/graftcode-gateway/releases/latest/download/gg_linux_amd64.deb \
 && dpkg -i /usr/app/gg.deb \
 && rm /usr/app/gg.deb \
 && apt-get clean \
 && rm -rf /var/lib/apt/lists/*

EXPOSE 80
EXPOSE 81

CMD ["gg","--modules","./energy-service/"]

The key line is the last one - gg (Graftcode Gateway) reads the module directory passed via --modules (./energy-service/, which includes your pyproject.toml), discovers all public methods in your module, and exposes them automatically. Port 80 handles service calls, port 81 serves Graftcode Vision.

Build and run the container:

docker build --no-cache --pull -t myenergyservice-py:test .
docker run -d -p 80:80 -p 81:81 --name graftcode_demo_py myenergyservice-py:test

Your Python service is now running and exposed through Graftcode Gateway.

Step 4. Explore the service in Graftcode Vision

Open http://localhost:81/GV in your browser.

You will see all public methods from your Python module - their names, parameter types, and return types. Graftcode Vision also provides:

  • A "Try it out" button to call methods live, directly from the browser.
  • A package manager command (npm, NuGet, PyPI, etc.) to install this service as a strongly-typed client in any other application.

Everything above works without any account - perfect for learning and local development. When you're ready for real-world usage, create a free account at portal.graftcode.com, set up a project, and copy its Project Key.

Then pass the key when starting your gateway:

CMD ["gg", "--modules", "./energy-service/", "--projectKey", "YOUR_PROJECT_KEY"]

A Project Key gives you:

  • Stable registry URL - consumers always find and update your Graft through a permanent address, so install commands don't change when you redeploy.
  • Portal visibility - see all your gateways and exposed services in one place at gateways.graftcode.com.
  • Access control - decide who can download your Grafts using package manager authentication and permissions.
  • MCP endpoint - Graftcode Gateway automatically exposes an MCP (Model Context Protocol) endpoint alongside your service, making your methods callable by AI agents and LLM-based tools out of the box.

Step 6. Call it from another app

Your service is now accessible from any application. From Graftcode Vision, select your target package type - for example PyPI - and copy the generated install command. That installs a Graft: a strongly-typed client that lets any app call your service methods directly.

Use the package and import paths from Vision or Gateway logs (for this sample the package is typically graft-pypi-energy-service==1.0.0). get_price() is synchronous and returns an int:

from graft_pypi_energy_service.energy_price_calculator import EnergyPriceCalculator
from graft_pypi_energy_service.graft_config import GraftConfig

GraftConfig.host = "ws://localhost:80/ws"

price = EnergyPriceCalculator.get_price()
print(price)

The generated PyPI Graft uses a flat module layout: import energy_price_calculator and graft_config (snake_case file names), not a nested energypricecalculator path.

No REST clients, no request/response models, no endpoint URLs in your code. When you add or update a public method, consumers update their Graft with a single package manager command.