Skip to content

Instantly share code, notes, and snippets.

@igmarin
Created March 25, 2026 18:04
Show Gist options
  • Select an option

  • Save igmarin/4169b1552327f3ae27111b053911d8a7 to your computer and use it in GitHub Desktop.

Select an option

Save igmarin/4169b1552327f3ae27111b053911d8a7 to your computer and use it in GitHub Desktop.
Proxy between Cursor and Ollama
from flask import Flask, request, Response
import requests
import json
app = Flask(__name__)
OLLAMA_URL = "http://localhost:11434/v1"
def forward(path, body):
try:
target_url = f"{OLLAMA_URL}/{path}"
print(f"\n{'='*50}")
print(f"→ PATH: /{path}")
print(f"→ BODY RAW: {json.dumps(body)[:500]}")
# Normalize: Cursor Responses API uses "input", Ollama uses "messages"
raw_messages = body.get('messages') or body.get('input') or []
if not raw_messages:
raw_messages = [{"role": "user", "content": "hello"}]
clean_messages = []
for msg in raw_messages:
role = msg.get('role')
if not role:
continue # skip objects without role
content = msg.get('content', '')
if isinstance(content, list):
texts = [c.get('text', '') for c in content
if isinstance(c, dict) and c.get('type') in ('input_text', 'text')]
content = '\n'.join(filter(None, texts)) or 'hello'
if content: # add only if there is content
clean_messages.append({'role': role, 'content': content})
if not clean_messages:
clean_messages = [{"role": "user", "content": "hello"}]
body['messages'] = clean_messages
body.pop('input', None)
body.pop('tools', None)
body.pop('tool_choice', None)
body.pop('store', None)
body.pop('stream_options', None)
body.pop('metadata', None)
body.pop('user', None)
is_stream = body.get('stream', False)
print(f"→ MESSAGES: {len(body['messages'])} | LAST: {body['messages'][-1]['content'][:100]}")
resp = requests.post(
target_url,
json=body,
headers={"Content-Type": "application/json"},
stream=is_stream,
timeout=120
)
print(f"← STATUS: {resp.status_code}")
if not is_stream:
print(f"← BODY: {resp.text[:300]}")
return Response(
resp.iter_content(chunk_size=1024) if is_stream else resp.content,
status=resp.status_code,
content_type=resp.headers.get('content-type', 'application/json')
)
except Exception as e:
print(f"💥 ERROR: {e}")
import traceback
traceback.print_exc()
return Response(
json.dumps({"error": {"message": str(e), "type": "proxy_error"}}),
status=500,
content_type='application/json'
)
@app.route('/v1/<path:path>', methods=['GET', 'POST', 'OPTIONS'])
def proxy_v1(path):
if request.method == 'OPTIONS':
r = Response()
r.headers['Access-Control-Allow-Origin'] = '*'
r.headers['Access-Control-Allow-Headers'] = '*'
r.headers['Access-Control-Allow-Methods'] = '*'
return r
return forward(path, request.get_json(silent=True) or {})
@app.route('/<path:path>', methods=['GET', 'POST', 'OPTIONS'])
def proxy_root(path):
if request.method == 'OPTIONS':
r = Response()
r.headers['Access-Control-Allow-Origin'] = '*'
r.headers['Access-Control-Allow-Headers'] = '*'
r.headers['Access-Control-Allow-Methods'] = '*'
return r
return forward(path, request.get_json(silent=True) or {})
if __name__ == '__main__':
print("🚀 Proxy on port 8080 → Ollama 11434")
app.run(host='0.0.0.0', port=8080, debug=False)
@igmarin

igmarin commented Mar 25, 2026

Copy link
Copy Markdown
Author

export HOMEBREW_AUTO_UPDATE_SECS=604800
alias brewup="brew update && brew upgrade && brew autoremove && brew cleanup && brew doctor"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment