Freefeed Mcp Server — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited Freefeed Mcp Server (Agent Skill) and scored it 96/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 1 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 1 flagged
The text {match} tells the agent to skip the normal "ask the user first" gate. Used adversarially it removes the human-in-the-loop check before destructive or sensitive actions, turning a normally-gated agent into a fire-and-forget executor.
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Use this skill to download and display images and other attachments from FreeFeed posts. This skill provides tools to fetch attachment files and show them inline when possible.
Available tools:
download_attachment - Download attachments with flexible output optionsget_attachment_image - Optimized for displaying images inlineget_post_attachments - Extract all attachment URLs from a postAlways use this skill when:
Triggers:
First, retrieve post data using standard FreeFeed tools:
# Get a specific post
post = get_post(post_id="...")
# Or get from timeline
timeline = get_timeline(timeline_type="home", limit=10)Posts contain attachment metadata in the attachments array:
# Each attachment has:
{
"id": "attachment-uuid",
"mediaType": "image", # or "video", "audio", "general"
"url": "https://media.freefeed.net/attachments/...",
"imageSizes": {
"t": {"url": "...", "width": 150, "height": 150}, # thumbnail
"t2": {"url": "...", "width": 300, "height": 300}, # medium
"o": {"url": "...", "width": 1024, "height": 768} # original
},
"fileName": "photo.jpg",
"fileSize": 245678
}Use get_attachment_image for inline display:
# Best for images - shows them directly to user
result = get_attachment_image(
attachment_url="https://media.freefeed.net/attachments/abc123",
max_bytes=2000000 # 2MB limit for inline display
)Or use download_attachment for more control:
# Download with options
result = download_attachment(
attachment_url="https://media.freefeed.net/attachments/abc123",
prefer_image=True, # Return image content when possible
max_bytes=2000000, # Max size for inline
save_path=None # Optional: save to file instead
)Images (recommended approach):
# For images, always use get_attachment_image
image = get_attachment_image(
attachment_url=attachment["url"]
)
# Claude will display the image inline to the userLarge files or videos:
# For files >2MB or non-images
result = download_attachment(
attachment_url=attachment["url"],
prefer_image=False # Just get URL
)
# Provide URL link to userMultiple attachments from a post:
# Extract all attachments first
attachments = get_post_attachments(post_id="abc123")
# Then download each one
for att in attachments["attachments"]:
if att["mediaType"] == "image":
get_attachment_image(attachment_url=att["url"])FreeFeed provides multiple image sizes. Choose appropriately:
IMPORTANT: Always use thumbnail size when auto-displaying images in timeline/feed!
Example:
# Get thumbnail size for timeline (RECOMMENDED)
thumbnail_url = attachment["imageSizes"]["t"]["url"]
get_attachment_image(attachment_url=thumbnail_url)
# Get medium size for better quality when requested
medium_url = attachment["imageSizes"]["t2"]["url"]
get_attachment_image(attachment_url=medium_url)
# Get original only when user explicitly asks
original_url = attachment["imageSizes"]["o"]["url"] # or just attachment["url"]
get_attachment_image(attachment_url=original_url)✅ Use get_attachment_image for images by default ✅ Check file size before downloading large files ✅ Use appropriate image size (thumbnail/medium/original) ✅ Download multiple images sequentially, not in parallel ✅ Inform user when images are too large to display inline
❌ Try to download images >2MB inline without warning user ❌ Use download_attachment when get_attachment_image is sufficient ❌ Download videos or large files without explicit user request ❌ Forget to handle cases where attachment URL might be invalid
⚡ IMPORTANT: Always show image previews automatically when displaying timeline!
When user asks to see their feed/timeline without specifically mentioning images, still show thumbnails:
# Get recent timeline
timeline = get_timeline(timeline_type="home", limit=10)
# ALWAYS show thumbnail previews for posts with images
for post in timeline["posts"]:
# Display post text/info first
print(f"@{post['author']}: {post['body']}")
# Then automatically show thumbnails for any images
attachments_data = lookup_attachments_in_response(post["attachments"])
for att in attachments_data:
if att["mediaType"] == "image":
# CRITICAL: Use thumbnail URL for timeline browsing (fast & small)
# FreeFeed provides image sizes: t (150px), t2 (300px), o (original)
# NOTE: imageSizes may not be present in timeline responses!
image_url = None
if "imageSizes" in att and att["imageSizes"]:
# Prefer thumbnail if available
if "t" in att["imageSizes"]:
image_url = att["imageSizes"]["t"].get("url")
# Fallback to base URL if no imageSizes
if not image_url:
# Construct thumbnail URL from base attachment URL
# Format: https://freefeed.net/attachments/{id} -> add /t for thumbnail
base_url = att.get("url", f"https://freefeed.net/attachments/{att['id']}")
# Try thumbnail endpoint first (smaller, faster)
image_url = f"{base_url}/t"
# Auto-display thumbnail - NO need to ask user
try:
get_attachment_image(attachment_url=image_url)
except:
# If thumbnail fails, try base URL as final fallback
if "/t" in image_url:
get_attachment_image(attachment_url=att.get("url", base_url))Why this matters:
# When user specifically asks about images in a post
post = get_post(post_id="...")
for att in post["attachments"]:
if att["mediaType"] == "image":
# Use original size when user explicitly requests images
get_attachment_image(attachment_url=att["url"])
print(f"📷 {att['fileName']} ({att['fileSize']} bytes)")# Get user's posts
posts = get_timeline(
timeline_type="posts",
username="alice",
limit=10
)
# Filter and show only images
for post in posts["posts"]:
for att in post.get("attachments", []):
if att["mediaType"] == "image":
get_attachment_image(attachment_url=att["url"])# When user wants to save attachment
download_attachment(
attachment_url="https://media.freefeed.net/attachments/...",
save_path="/tmp/freefeed_image.jpg"
)Handle common errors gracefully:
try:
result = get_attachment_image(attachment_url=url)
if not result:
print("⚠️ Could not load image. URL may be invalid.")
except Exception as e:
print(f"❌ Error downloading image: {e}")
print("🔗 View in browser: " + url)User: покажи картинку из того поста про кино
Claude: [calls get_post for the cinema post]
[extracts attachment URL]
[calls get_attachment_image with URL]
[displays image to user]User: show me photos from @alice's recent posts
Claude: [calls get_timeline for alice's posts]
[filters posts with images]
[calls get_attachment_image for each]
[displays images with post context]User: покажи вложение из директа
Claude: [gets attachment URL]
[checks file size: 5MB]
[calls download_attachment with prefer_image=false]
"This file is too large to display inline (5MB).
You can view it here: [URL]"max_bytes)Combine with FreeFeed tools:
get_post → get_attachment_image (show images from specific post)get_timeline → get_post_attachments → get_attachment_image (gallery view)search_posts → filter images → get_attachment_image (search images)Problem: Image won't display
Problem: Slow loading
Problem: Wrong image shown
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.