Indie Hub submission for the Puch AI Hackathon Team: Indie Hub • Member: Mantej Singh • Server: Luna MCP Server
Thin, production-oriented MCP (Model Context Protocol) HTTP server that:
- Implements the Puch AI MCP contract (single
/mcpJSON-RPC 2.0 POST endpoint) - Extends the official Puch AI MCP Starter
- Bridges advanced AI & multimodal workloads to Luna Services (repo) — Gemini code generation, voice synthesis, Supabase data, and image transforms
- Ships a developer tool suite (GitHub automation, CI triggers, scaffolding, tests, Docker build, image utilities)
- Auth: Bearer token (strict) + optional GitHub OAuth (future-ready)
- Deploys: local (
uvicorn), public tunnel (ngrok), containerized (docker-compose) - Deploys: local (
uvicorn), public tunnel (ngrok), containerized (docker-compose), serverless (Vercel)
| Method | Type | Description |
|---|---|---|
code_gen |
Forwarder | Gemini-style code generation via Luna Services (/api/ai/code) with graceful fallback |
git_clone |
Local | Shallow + partial clone (--depth 1 --filter=blob:none) into ./repos/<name> |
ci_trigger |
Forwarder | Dispatch a GitHub Actions workflow (requires GITHUB_TOKEN) |
scaffold_project |
Local | Create a minimal Python package + optional test |
run_tests |
Local | Execute pytest -q; summarizes result |
img_bw |
Local | Fetch image URL → convert to grayscale (Pillow) → base64 PNG |
voice_speak |
Forwarder | Text-to-audio via Luna Services (/api/ai/voice) |
bw_remote |
Forwarder | Remote grayscale transform through Luna Services (/api/image/bw) |
create_branch |
GitHub | Create branch from base ref |
commit_file |
GitHub | Create/update file (base64 content) |
open_pr |
GitHub | Open pull request |
list_issues |
GitHub | Enumerate open issues |
validate |
Local | Return server validation number |
code_gen now supports simulated streaming via Server-Sent Events (SSE). While upstream model
tokens are currently buffered server-side, the server slices and emits chunks incrementally for
responsive clients.
SSE endpoint:
GET /public/stream?method=code_gen&prompt=Write%20a%20Python%20CLI
Events:
start– initial metadata- (default) – chunk messages:
{ "chunk": "..." } end– completion marker{ "ok": true }error–{ "error": "..." }
Example curl consumption:
curl -N 'https://<host>/public/stream?method=code_gen&prompt=FizzBuzz%20in%20Rust'Client JS example:
const es = new EventSource('/public/stream?method=code_gen&prompt=FizzBuzz');
es.onmessage = e => { const {chunk} = JSON.parse(e.data); if(chunk) append(chunk); };
es.addEventListener('end', ()=> es.close());Acceptance test only depends on:
code_gen,git_clone,img_bw
| Name | Required | Purpose |
|---|---|---|
AUTH_TOKEN |
Yes | Bearer token expected in Authorization: Bearer <token> |
LUNA_URL |
No (default) | Upstream Luna Services base URL (default http://localhost:8000) |
GITHUB_CLIENT_ID / GITHUB_CLIENT_SECRET |
No | For optional OAuth extension |
GITHUB_TOKEN |
Conditional | Needed for write GitHub APIs & CI triggers |
SUPABASE_URL / SUPABASE_KEY |
Optional | Passed through for Luna Services usage |
NGROK_TOKEN |
Recommended | For public tunneling via docker-compose ngrok service |
PUBLIC_TOOLS |
Optional | Comma list of tools exposed at /public/execute (default code_gen,validate) |
PUBLIC_BASE_URL |
Optional | External base URL used in OAuth metadata |
OAUTH_SIGNING_KEY |
Optional | HMAC secret for signing short-lived auth tokens |
Sample file: .env.example
Prereqs:
- Python 3.11+
uv(fast dependency manager) – https://github.com/astral-sh/uvgit,ngrok(if tunneling), optional Docker
uv venv
source .venv/bin/activate
uv sync
cp .env.example .env
# Edit .env and set AUTH_TOKEN=your_secret
uvicorn mcp-bearer-token.luna_mcp:app --host 0.0.0.0 --port 8086 --reload
# Programmatic import alternative:
# from mcp_bearer_token import appPublic tunnel:
ngrok http 8086Once ngrok URL is live (e.g. https://abc123.ngrok-free.app):
/mcp connect https://abc123.ngrok-free.app/mcp your_secretTest tools:
/mcp call code_gen '{"prompt":"Write hello world in Rust"}'
/mcp call git_clone '{"url":"https://github.com/tensorflow/tensorflow"}'
/mcp call img_bw '{"image_url":"https://picsum.photos/300"}'All should return a JSON-RPC result within 5 seconds.
docker compose up --buildServices:
mcp: FastAPI app on8086ngrok: Tunnel container (needsNGROK_TOKEN)
Steps:
- Open
mcp-bearer-token/luna_mcp.py. - Define an async function and decorate it with
@tool.
Example:
@tool("echo", "Echo back a message")
async def echo(message: str) -> dict:
return {"echo": message}Guidelines:
- Return JSON-serializable data only.
- Keep execution under a few seconds for good UX.
- Avoid side-effects in tools you expose publicly.
- All
/mcpcalls must includeAuthorization: Bearer <AUTH_TOKEN> - GitHub mutations require either:
GITHUB_TOKENPAT (scopes:repo,workflow)- Future: OAuth exchange (placeholder in
github_oauth/oauth_config.py)
Unauthorized calls → HTTP 401 (not JSON-RPC envelope).
Unauthenticated endpoints:
GET /public/health– minimal status + public tool listGET /public/tools– list public toolsPOST /public/execute– invoke allow‑listed tool (sanitized output)GET /public/stream– SSE stream wrapper (chunked output for streaming-capable tools)GET /public/metrics– aggregated latency metrics (avg, p95) per tool
Configure with PUBLIC_TOOLS env var (comma separated). Keep this list restricted to idempotent, non-sensitive tools.
Endpoints provided for future full auth code flow:
/.well-known/oauth-authorization-server/authorize/token
Currently they return placeholder responses. To harden:
- Generate an
OAUTH_SIGNING_KEY(32+ random bytes). - Implement user consent & redirect with
codeparam in/authorize. - Exchange
codefor JWT access token in/token(signed via HS256).
Example minimal signing snippet (not yet wired):
import jwt, time, os
token = jwt.encode({"sub":"user123","exp":int(time.time())+900}, os.environ['OAUTH_SIGNING_KEY'], algorithm='HS256')PRs welcome to complete the flow.
Vercel can serve the FastAPI app via ASGI using vercel-python. Quick path:
- Add a
vercel.jsonwith a serverless function entry. - Expose
AUTH_TOKEN(and others) as Vercel Project Environment Variables. - Deploy via
vercelCLI or Git integration.
Sample vercel.json (add to repo root):
{
"functions": {
"api/index.py": { "runtime": "python3.11" }
},
"routes": [
{ "src": "/mcp", "dest": "/api/index.py" },
{ "src": "/public/(.*)", "dest": "/api/index.py" },
{ "src": "/(.*)", "dest": "/public/index.html" }
]
}Create api/index.py wrapper that loads the FastAPI app:
from mcp_bearer_token import app as _app
from fastapi.middleware.cors import CORSMiddleware
app = _app # Vercel expects variable named app
# (Optional) adjust any middleware for serverless nuances hereNote: For long‑running operations (e.g., git clone of large repos) serverless timeouts may apply. Consider keeping those tools disabled via PUBLIC_TOOLS or offloading heavy tasks.
If you receive HTTP 405 when connecting a MCP client:
- Ensure endpoint URL includes
/mcp(not root). - Confirm POST is allowed by making a manual request:
curl -i -X POST https://<your-host>/mcp -H 'Authorization: Bearer <token>' -d '{"jsonrpc":"2.0","id":1,"method":"validate","params":{}}'- GET
/mcpshould return discovery JSON (unauthenticated) confirming the route. - If deploying on Vercel, verify
vercel.jsonroutes include"^/(mcp|... )$"mapping to your function.
Checklist:
-
/mcppath present - POST supported
- Auth header present
- No extra path prefix (e.g.
/api/mcpunless client configured)
git_cloneuses--depth 1 --filter=blob:nonefor speed (<5s on large repos)- Basic test suite (
pytest -q) ensures health endpoint & tool registry presence - CI runs ruff + mypy + pytest + docker build + Trivy scan
code_gengracefully falls back to a deterministic sample if upstream unreachableimg_bwenforces network + Pillow decode boundaries (default httpx timeout 20s)run_testsdegrades ifpytestmissing (returns informative result)
See: ARCHITECTURE.md
- Puch AI MCP Starter: https://github.com/TurboML-Inc/mcp-starter
- Luna Services Backend: https://github.com/Drago-03/Luna-Services
- Puch AI Hackathon: https://puch.ai/hack
- Mermaid Live: https://mermaid.live
| Item | Status |
|---|---|
| Bearer Auth | ✅ |
| Tools: core 6 | ✅ |
| Forwarders to Luna Services | ✅ |
| JSON-RPC shape | ✅ |
| ngrok integration | ✅ |
| docker-compose | ✅ |
| Dockerfile | ✅ |
| Docs + diagrams | ✅ |
| Quickstart script | ✅ |
| Acceptance script | ✅ |
| Basic tests | ✅ |
bash quickstart.sh
# Copy ngrok URL
/mcp connect https://<ngrok>.ngrok-free.app/mcp my_secret
/mcp call code_gen '{"prompt":"Write hello world in Rust"}'
/mcp call git_clone '{"url":"https://github.com/tensorflow/tensorflow"}'
/mcp call img_bw '{"image_url":"https://picsum.photos/300"}'
/mcp call validate '{}'
./acceptance_test.sh https://<ngrok>.ngrok-free.app my_secret