This is a submission for the Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady

What I Built

SlothVault is a local-first personal RAG utility built for anyone too tired or busy to manually sort, tag, and organize digital clutter.

Every day, developers and researchers accumulate messy context fragments:

  • Home lab and Wi-Fi credentials
  • Cloud subscription renewal dates and invoice amounts
  • Medical appointments and task deadlines

Most productivity guides advise spending hours building complex databases in Notion or Obsidian. SlothVault takes the lazy approach: dump your unorganized notes into a local vault and let an open-weight agent fetch what you need in seconds.

  1. Zero Manual Tagging: It ingests raw notes, credentials, and .txt files on the fly.
  2. MCP Tool Integration: Exposes standard Model Context Protocol (MCP) tool contracts (retrieve_from_vault and add_to_vault).
  3. 2-Sentence Brief: Uses local embeddings and an open-weight language model to extract the exact fact and output a concise brief.

Demo

Code

import json import torch import numpy as np import gradio as gr from transformers import pipeline from sentence_transformers import SentenceTransformer from sklearn.metrics.pairwise import cosine_similarity # 1. Load Local Open-Weight Models embed_model = SentenceTransformer("all-MiniLM-L6-v2") device = "cuda" if torch.cuda.is_available() else "cpu" llm_pipeline = pipeline( "text-generation", model="Qwen/Qwen2.5-1.5B-Instruct", torch_dtype=torch.bfloat16 if torch.cuda.is_available() else torch.float32, device_map="auto" if torch.cuda.is_available() else None ) # 2. In-Memory Vault & Seed Data vault_docs = [ "WiFi Password for Home Lab is 'lazy_sloth_42'. Do not share externally.", "Invoice #8841 from Cloud hosting was $45.20, due on November 5th.", "Doctor appointment rescheduled to Friday at 4:30 PM with Dr. Sharma.", "Project roadmap milestone 2 requires TabPFN model benchmarking by next Tuesday." ] vault_embeddings = embed_model.encode(vault_docs) # 3. Model Context Protocol (MCP) Tool Functions def mcp_retrieve_from_vault(query: str, top_k: int = 2): global vault_docs, vault_embeddings if not vault_docs: return [] q_vec = embed_model.encode([query]) scores = cosine_similarity(q_vec, vault_embeddings)[0] top_indices = np.argsort(scores)[::-1][:top_k] return [{"text": vault_docs[i], "similarity_score": round(float(scores[i]), 3)} for i in top_indices] def mcp_add_to_vault(new_text: str): global vault_docs, vault_embeddings cleaned = new_text.strip() if not cleaned: return "Empty note." vault_docs.append(cleaned) new_embedding = embed_model.encode([cleaned]) vault_embeddings = np.vstack([vault_embeddings, new_embedding]) return f"Added to vault. Total items: {len(vault_docs)}" # 4. Agent Synthesis SYSTEM_PROMPT = ( "You are SlothVault. The user is exhausted. You have executed the MCP tool " "'retrieve_from_vault' and received matching records. " "Give the exact answer in 1-2 punchy sentences. " "End with a short sloth remark like 'Now go back to resting. 🦥'." ) def sloth_agent_search(query: str): if not query.strip(): return "Ask something you're too lazy to search for!" retrieved = mcp_retrieve_from_vault(query, top_k=2) context_str = "\n".join([f"- {r['text']} (Match: {r['similarity_score']})" for r in retrieved]) messages = [ {"role": "system", "content": SYSTEM_PROMPT}, {"role": "user", "content": f"Query: {query}\n\nContext:\n{context_str}"} ] res = llm_pipeline(messages, max_new_tokens=120, temperature=0.2) answer = res[0]["generated_text"][-1]["content"].strip() trace = ( f"``` {% endraw %} json\n" f"// MCP Tool Execution Trace\n" f'{{"tool": "retrieve_from_vault", "query": "{query}", "matches": {len(retrieved)}}}\n' f" {% raw %} 


\n\n"
f"Retrieved Context:\n{context_str}\n\n"
f"---\n"
f"### Sloth Answer\n{answer}"
)
return trace

def handle_upload(file_obj, raw_text):
count = 0
if file_obj is not None:
with open(file_obj.name, "r", encoding="utf-8", errors="ignore") as f:
for line in f.readlines():
if line.strip():
mcp_add_to_vault(line.strip())
count += 1
if raw_text and raw_text.strip():
mcp_add_to_vault(raw_text.strip())
count += 1
return f"Successfully ingested {count} item(s) into vault."

5. Gradio Interface

with gr.Blocks(theme=gr.themes.Soft(), title="SlothVault") as demo:
gr.Markdown("# SlothVault: Zero-Effort Local MCP + RAG Agent")
gr.Markdown("Stop organizing notes manually. Dump raw clutter and let an open-weight agent retrieve it.")

with gr.Tab(" Ask the Sloth Agent"): query_in = gr.Textbox(label="Ask anything:", value="What is my home lab wifi password and when is the cloud bill due?") search_btn = gr.Button(" Find It For Me", variant="primary") output_box = gr.Markdown() search_btn.click(fn=sloth_agent_search, inputs=query_in, outputs=output_box) with gr.Tab(" Dump More Clutter (Add Notes)"): note_in = gr.Textbox(label="Paste note or snippet:", placeholder="e.g., Gate code is 8842") file_in = gr.File(label="Upload .txt file", file_types=[".txt"]) add_btn = gr.Button(" Ingest Without Organizing") status_box = gr.Markdown() add_btn.click(fn=handle_upload, inputs=[file_in, note_in], outputs=status_box) 

demo.launch(share=True)

How I Built It
SlothVault combines open-weight models, dense semantic retrieval, and the Model Context Protocol (MCP):

Standardized MCP Tool Contracts: Instead of building an ad-hoc search script, the data operations implement retrieve_from_vault and add_to_vault tool definitions, ensuring compatibility with standard agent frameworks.

Fast Local Vector Search: sentence-transformers/all-MiniLM-L6-v2 embeds text into 384-dimensional vectors. Cosine similarity matching retrieves the top-ranked context in milliseconds without a heavy external vector database.

Local Open-Weight Reasoning: Qwen/Qwen2.5-1.5B-Instruct synthesizes the retrieved chunks on-device, extracting precise facts and avoiding generative hallucinations.

Why Does Open Innovation Matter?
Absolute Privacy: Personal notes, Wi-Fi credentials, medical reminders, and invoices never leave the machine. Running inference locally keeps sensitive personal data off third-party servers.

Zero Operating Cost: Powered by open weights, the agent runs entirely free of token limits, monthly subscriptions, or cloud API paywalls.

Offline Reliability: Because the models run on-device, the agent functions normally on a laptop even without an internet connection.

Prize Categories
Top Prize: Slow and Steady ($250 USD)