New to Mixpeek? Follow the first tab — MVS Standalone — end to end. It’s the shortest path to a working search (under 60 seconds) and needs nothing but an API key. The other tabs wire that same search into an agent (LangChain, MCP) or call it over REST once you’ve created a retriever.
- MVS Standalone (fastest)
- LangChain Agent
- MCP (Claude)
- REST API
Already have embeddings? Skip extraction — search in under 60 seconds.
pip install mixpeek
export MIXPEEK_API_KEY="mxp_sk_replace_me"
1
Create a standalone namespace
import os
from mixpeek import Mixpeek
client = Mixpeek(api_key=os.environ["MIXPEEK_API_KEY"])
ns = client.namespaces.create(
namespace_name="my-search", # required, 3–64 chars; the id is auto-generated
mode="standalone", # bring your own vectors — no extractors
)
2
Upsert your vectors
client.namespaces.documents.upsert(
namespace_id=ns.namespace_id,
documents=[{
"document_id": "doc-001",
"vectors": {"embedding": [0.12, -0.34, 0.56]}, # your embedding
"payload": {"title": "First document", "category": "demo"},
}],
)
3
Search
Vectors are searchable within 10–30 seconds of upsert (the index flushes in the background). For immediate verification, add a short poll:
import time
# Wait for indexing
time.sleep(15)
results = client.search(
namespace_id=ns.namespace_id,
queries=[{
"vector_name": "embedding",
"vector": [0.15, -0.28, 0.44], # query embedding
"top_k": 10,
}],
)
for hit in results["documents"]:
print(f"{hit['score']:.3f} | {hit['payload']['title']}")
MVS infers vector dimensions on first write — no schema needed. When you’re ready for automatic extraction, promote your namespace to Managed.
Build a LangChain agent with a Poll
video_search tool backed by Mixpeek.pip install mixpeek langchain langchain-openai
export MIXPEEK_API_KEY="mxp_sk_replace_me"
export OPENAI_API_KEY="sk-replace_me"
1
Create namespace, bucket, and collection
import os
from mixpeek import Mixpeek
client = Mixpeek(api_key=os.environ["MIXPEEK_API_KEY"])
# Managed namespace — `namespace_name` is the only required field. You don't
# register extractors up front; the collection's `features` (below) auto-provision
# whatever pipeline the namespace needs.
ns = client.namespaces.create(namespace_name="agent-video-demo")
# Scope the client to the namespace you just created — every call below sends it
# as the X-Namespace header, which bucket/collection create and search require.
client.namespace = ns.namespace_id
bucket = client.buckets.create(
bucket_name="demo-videos",
# "video" is the standard source property name per modality —
# collections created with `features` wire to it automatically.
bucket_schema={"properties": {"video": {"type": "video"}}},
)
# Create the collection by picking a feature — Mixpeek resolves the
# pipeline and default input wiring (see /processing/features).
col = client.collections.create(
collection_name="video-scenes",
source={"type": "bucket", "bucket_ids": [bucket.bucket_id]},
features=["video_search"],
)
2
Upload and process
# Upload the video to the bucket, then trigger the collection to process it.
client.buckets.upload(
bucket.bucket_id,
url="https://storage.googleapis.com/mixpeek-public-demo/videos/sample-product-demo.mp4",
)
result = client.collections.trigger(col.collection_id)
client.tasks.get(task_id=result.task_id) until the status is terminal — COMPLETED or COMPLETED_WITH_ERRORS (1-5 min). Don’t wait only for COMPLETED, or a batch that finished with some failed items will hang your loop.3
Create a retriever and wire it as a tool
from langchain.tools import Tool
from langchain_openai import ChatOpenAI
from langchain.agents import AgentExecutor, create_openai_tools_agent
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
ret = client.retrievers.create(
retriever_name="agent-video-search",
input_schema={"query_text": {"type": "text", "required": True}},
collection_identifiers=[col.collection_id],
stages=[{
"stage_name": "search",
"stage_type": "filter",
"config": {
"stage_id": "feature_search",
"parameters": {
"searches": [{
"feature_uri": "mixpeek://universal_extractor@v1/gemini-embedding-2",
"query": {"input_mode": "text", "value": "{{INPUT.query_text}}"},
"top_k": 50
}],
"final_top_k": 20
}
}
}]
)
def search_video(query: str) -> str:
results = client.retrievers.execute(
retriever_id=ret.retriever_id,
inputs={"query_text": query},
)
return "\n".join(
f"[{r.get('start_time_s','?')}s] (score: {r.score:.3f}) {r.get('description','')}"
for r in results.documents
) or "No results found."
video_tool = Tool(name="video_search", description="Search indexed video by natural language", func=search_video)
llm = ChatOpenAI(model="gpt-4o", temperature=0)
prompt = ChatPromptTemplate.from_messages([
("system", "You answer questions about video content. Use video_search to find relevant moments."),
("human", "{input}"), MessagesPlaceholder(variable_name="agent_scratchpad"),
])
agent = create_openai_tools_agent(llm, [video_tool], prompt)
executor = AgentExecutor(agent=agent, tools=[video_tool], verbose=True)
print(executor.invoke({"input": "What product features are shown?"})["output"])
Add Mixpeek as a tool in Claude Desktop or Claude Code — no code required.Restart Claude and ask: “What Mixpeek tools do you have access to?”
See the full MCP reference for per-retriever servers and troubleshooting.
- Claude Desktop
- Claude Code
Open
claude_desktop_config.json and add:{
"mcpServers": {
"mixpeek-retrieval": {
"url": "https://mcp.mixpeek.com/retrieval/mcp",
"headers": {
"Authorization": "Bearer YOUR_API_KEY"
}
}
}
}
Add
.mcp.json to your project root:{
"mcpServers": {
"mixpeek-retrieval": {
"url": "https://mcp.mixpeek.com/retrieval/mcp",
"headers": {
"Authorization": "Bearer YOUR_API_KEY"
}
}
}
}
| Scope | URL | Tools |
|---|---|---|
| Full | https://mcp.mixpeek.com/mcp | 48 |
| Ingestion | https://mcp.mixpeek.com/ingestion/mcp | 20 |
| Retrieval | https://mcp.mixpeek.com/retrieval/mcp | 11 |
| Admin | https://mcp.mixpeek.com/admin/mcp | 17 |
Call Each result is a document with a top-level
POST /v1/retrievers/{id}/execute from any language.import os
import requests
MIXPEEK_API_KEY = os.environ["MIXPEEK_API_KEY"]
MIXPEEK_NAMESPACE = os.environ["MIXPEEK_NAMESPACE"] # the namespace_id (ns_...) returned at creation
RETRIEVER_ID = os.environ["MIXPEEK_RETRIEVER_ID"] # the retriever_id (ret_...) from retrievers.create
HEADERS = {
"Authorization": f"Bearer {MIXPEEK_API_KEY}",
"X-Namespace": MIXPEEK_NAMESPACE,
"Content-Type": "application/json",
}
resp = requests.post(
f"https://api.mixpeek.com/v1/retrievers/{RETRIEVER_ID}/execute",
headers=HEADERS,
json={"inputs": {"query_text": "safety regulations"}},
)
results = resp.json()["documents"]
score plus the document’s own fields (e.g. content, start_time_s) flattened to the top level. Wrap this call as a tool in any agent framework — OpenAI function calling, CrewAI, LlamaIndex, or plain HTTP.See the API reference for full request and response details.
