Gemini Protocol Support
This document provides comprehensive information about the Gemini protocol support in the Gopher & Gemini MCP Server.
Overview
The Gemini protocol is a modern, lightweight internet protocol that sits between Gopher and the Web. It features:
- Mandatory TLS encryption for all connections
- Simple text-based markup (gemtext) for content
- Privacy-focused design with minimal client tracking
- Certificate-based authentication for enhanced security
Features
Core Protocol Support
- ✅ Full Gemini 0.24.1 specification compliance
- ✅ TLS 1.2+ with SNI support
- ✅ All status codes (10-69) handled
- ✅ Native gemtext parsing and structured output
- ✅ Binary content detection and handling
- ✅ URL validation and normalization
Security Features
- ✅ TOFU (Trust-on-First-Use) certificate validation
- ✅ Client certificate generation and management
- ✅ Scope-based certificate isolation
- ✅ Certificate fingerprint verification
- ✅ Secure certificate storage
- ✅ Host allowlist support
Performance Features
- ✅ Intelligent response caching
- ✅ Async/await architecture
- ✅ Connection pooling and reuse
- ✅ Configurable timeouts and limits
- ✅ Memory-efficient streaming
Usage
Basic Fetching
# Fetch a Gemini page
result = await gemini_fetch("gemini://geminiprotocol.net/")
# The result will be one of:
# - GeminiGemtextResult: For gemtext content
# - GeminiSuccessResult: For other content types
# - GeminiInputResult: For input requests
# - GeminiRedirectResult: For redirects
# - GeminiErrorResult: For errors
# - GeminiCertificateResult: For certificate requests
Response Types
GeminiGemtextResult
For text/gemini content, returns a structured document:
{
"kind": "gemtext",
"document": {
"lines": [
{"type": "heading1", "text": "Welcome to Gemini"},
{"type": "text", "text": "This is a paragraph."},
{"type": "link", "url": "gemini://example.org/", "text": "Example Link"}
],
"links": [
{"url": "gemini://example.org/", "text": "Example Link", "line_number": 3}
],
"headings": [
{"level": 1, "text": "Welcome to Gemini", "line_number": 1}
]
},
"raw_content": "# Welcome to Gemini\nThis is a paragraph.\n=> gemini://example.org/ Example Link",
"charset": "utf-8",
"size": 67
}
GeminiSuccessResult
For non-gemtext text content (e.g. text/plain):
{
"kind": "success",
"mime_type": {
"full_type": "text/plain",
"main_type": "text",
"sub_type": "plain",
"charset": "utf-8",
"is_text": true,
"is_gemtext": false
},
"content": "Plain text content here",
"size": 23
}
GeminiBinaryResult
For binary content, only metadata is returned — the raw bytes are not inlined (a 1 MB body would be ~1.4M base64 characters of context). Re-fetch the resource directly if you need the bytes.
{
"kind": "binary",
"mime_type": {
"full_type": "image/png",
"main_type": "image",
"sub_type": "png",
"is_text": false,
"is_gemtext": false
},
"size": 1048576,
"note": "Binary content not returned to preserve context"
}
GeminiInputResult
For input requests (status 10-11):
GeminiRedirectResult
For redirects (status 30-31):
GeminiErrorResult
For errors (status 40-69):
{
"kind": "error",
"status": 51,
"message": "Not found",
"is_temporary": false,
"is_server_error": true
}
Security
TOFU Certificate Validation
The client implements Trust-on-First-Use (TOFU) certificate validation:
- First connection: Certificate fingerprint is stored
- Subsequent connections: Fingerprint is verified against stored value
- Certificate changes: User intervention required (in MCP context, this means an error)
TOFU data is stored in ~/.gemini/tofu.json by default.
Client Certificates
The client supports automatic client certificate generation and management:
- Scope-based isolation: Certificates are generated per hostname or path scope
- Automatic generation: Certificates are created on-demand when requested
- Secure storage: Private keys are stored securely in
~/.gemini/certs/ - Certificate reuse: Same certificate is used for the same scope
Host Allowlists
Configure allowed hosts for additional security:
Configuration
Environment Variables
| Variable | Description | Default | Example |
|---|---|---|---|
GEMINI_MAX_RESPONSE_SIZE |
Maximum response size in bytes | 1048576 |
2097152 |
GEMINI_TIMEOUT_SECONDS |
Request timeout in seconds | 30 |
60 |
GEMINI_CACHE_ENABLED |
Enable response caching | true |
false |
GEMINI_CACHE_TTL_SECONDS |
Cache time-to-live in seconds | 300 |
600 |
GEMINI_MAX_CACHE_ENTRIES |
Maximum cache entries | 1000 |
2000 |
GEMINI_ALLOWED_HOSTS |
Comma-separated allowed hosts | None |
example.org,test.org |
GEMINI_TOFU_ENABLED |
Enable TOFU certificate validation | true |
false |
GEMINI_TOFU_REJECT_EXPIRED |
Fail closed on certificates outside their validity window | false |
true |
GEMINI_CLIENT_CERTS_ENABLED |
Enable automatic client certificate management | true |
false |
GEMINI_TOFU_STORAGE_PATH |
TOFU storage file path | ~/.gemini/tofu.json |
/custom/path/tofu.json |
GEMINI_CLIENT_CERTS_STORAGE_PATH |
Client certificate storage directory | ~/.gemini/certs/ |
/custom/path/certs/ |
GEMINI_MAX_RENDERED_CHARS |
LLM-facing cap on returned text characters (0 = unlimited) | 50000 |
100000 |
GEMINI_REQUESTS_PER_MINUTE |
Per-host request rate cap (0 = unlimited) | 0 |
60 |
GEMINI_MAX_CONCURRENT_REQUESTS |
Cap on simultaneous in-flight fetches (0 = unlimited) | 0 |
20 |
GEMINI_DENIED_MIME_TYPES |
Comma-separated MIME deny list (supports type/*) |
None |
text/html,image/* |
Advanced Configuration
from gopher_mcp.gemini_client import GeminiClient
# Custom client configuration. TLS 1.2 is the enforced minimum (TLS 1.2 and
# 1.3 are supported) and server trust is handled by TOFU, so there are no TLS
# version or hostname-verification knobs. Client certificates are generated
# and managed automatically when client_certs_enabled is True.
client = GeminiClient(
max_response_size=2 * 1024 * 1024, # 2MB
timeout_seconds=60.0,
cache_enabled=True,
cache_ttl_seconds=600,
max_cache_entries=2000,
allowed_hosts=["geminiprotocol.net", "warmedal.se"],
tofu_enabled=True,
tofu_reject_expired=True,
client_certs_enabled=True,
client_certs_storage_path="/custom/path/certs/",
)
TLS and certificate trust are not user-tuned
The internal TLSConfig does carry client_cert_path / client_key_path fields, but they are populated automatically by the client-certificate manager per host/scope — you never set them yourself. Likewise there is no min_version override exposed through configuration; TLS 1.2 is enforced in code.
Error Handling
The Gemini client provides comprehensive error handling:
Connection Errors
- DNS resolution failures
- Connection timeouts
- TLS handshake failures
- Certificate validation errors
Protocol Errors
- Invalid status codes
- Malformed responses
- Content too large
- Invalid URLs
Security Errors
- TOFU validation failures
- Certificate verification errors
- Host not allowed
- TLS version mismatches
Best Practices
For AI Assistants
- Handle all response types: Be prepared for input requests, redirects, and errors
- Respect certificate requirements: Some sites require client certificates
- Follow redirects carefully: Check for redirect loops
- Parse gemtext properly: Use the structured document format for better understanding
- Handle errors gracefully: Provide helpful error messages to users
For Developers
- Enable TOFU: Always use TOFU certificate validation in production
- Configure timeouts: Set appropriate timeouts for your use case
- Use caching: Enable caching for better performance
- Monitor certificate changes: Log TOFU validation failures
- Implement host allowlists: Restrict access to trusted hosts when needed
Troubleshooting
Common Issues
- Certificate validation failures
- Check TOFU storage permissions
- Verify certificate hasn't changed unexpectedly
-
Ensure system time is correct
-
Connection timeouts
- Increase timeout values
- Check network connectivity
-
Verify server is responding
-
TLS handshake failures
- Ensure TLS 1.2+ support
- Check cipher suite compatibility
-
Verify SNI support
-
Client certificate issues
- Check certificate storage permissions
- Verify certificate generation
- Ensure proper scope configuration
Debug Logging
Enable debug logging for troubleshooting by setting the server log level:
Standards Compliance
The implementation follows these specifications:
- Gemini Protocol Specification v0.24.1
- RFC 5246 - TLS 1.2
- RFC 8446 - TLS 1.3
- RFC 6066 - TLS Extensions (SNI)
- RFC 5280 - X.509 Certificates