Expose Backend
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.
Step 5. Run with a Project Key (recommended for real-world usage)
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.