Skip to content

Drago-03/Luna-MCP-Services

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

33 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Luna-MCP-Server

CI Ruff mypy Security Scan pre-commit.ci status codecov

Coverage Icicle Graph

Coverage Icicle

Indie Hub submission for the Puch AI Hackathon Team: Indie Hub • Member: Mantej Singh • Server: Luna MCP Server

Logo

Thin, production-oriented MCP (Model Context Protocol) HTTP server that:

  • Implements the Puch AI MCP contract (single /mcp JSON-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)

Tool Registry (MCP Methods)

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

Streaming Support

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


Environment Variables

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


Quick Start (Local Dev)

Prereqs:

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 app

Public tunnel:

ngrok http 8086

Connect Puch AI MCP Client

Once ngrok URL is live (e.g. https://abc123.ngrok-free.app):

/mcp connect https://abc123.ngrok-free.app/mcp your_secret

Test 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

docker compose up --build

Services:

  • mcp: FastAPI app on 8086
  • ngrok: Tunnel container (needs NGROK_TOKEN)

Adding a New Tool

Steps:

  1. Open mcp-bearer-token/luna_mcp.py.
  2. 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.

Auth Model

  1. All /mcp calls must include Authorization: Bearer <AUTH_TOKEN>
  2. GitHub mutations require either:
    • GITHUB_TOKEN PAT (scopes: repo, workflow)
    • Future: OAuth exchange (placeholder in github_oauth/oauth_config.py)

Unauthorized calls → HTTP 401 (not JSON-RPC envelope).

Public Facade

Unauthenticated endpoints:

  • GET /public/health – minimal status + public tool list
  • GET /public/tools – list public tools
  • POST /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.

OAuth (Experimental Placeholder)

Endpoints provided for future full auth code flow:

  • /.well-known/oauth-authorization-server
  • /authorize
  • /token

Currently they return placeholder responses. To harden:

  1. Generate an OAUTH_SIGNING_KEY (32+ random bytes).
  2. Implement user consent & redirect with code param in /authorize.
  3. Exchange code for 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 Deployment

Vercel can serve the FastAPI app via ASGI using vercel-python. Quick path:

  1. Add a vercel.json with a serverless function entry.
  2. Expose AUTH_TOKEN (and others) as Vercel Project Environment Variables.
  3. Deploy via vercel CLI 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 here

Note: 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.

405 Method Not Allowed (Troubleshooting MCP Connect)

If you receive HTTP 405 when connecting a MCP client:

  1. Ensure endpoint URL includes /mcp (not root).
  2. 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":{}}'
  1. GET /mcp should return discovery JSON (unauthenticated) confirming the route.
  2. If deploying on Vercel, verify vercel.json routes include "^/(mcp|... )$" mapping to your function.

Checklist:

  • /mcp path present
  • POST supported
  • Auth header present
  • No extra path prefix (e.g. /api/mcp unless client configured)

Test / Reliability Notes

  • git_clone uses --depth 1 --filter=blob:none for 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_gen gracefully falls back to a deterministic sample if upstream unreachable
  • img_bw enforces network + Pillow decode boundaries (default httpx timeout 20s)
  • run_tests degrades if pytest missing (returns informative result)

Architecture

See: ARCHITECTURE.md


References


Acceptance Checklist

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

How to Demo (Condensed)

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

About

Punch AI Hackathon Solution

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors