Peek
Peek is an MCP server that lets an AI agent take a photo using your camera and receive the image plus its saved file path.
Capture a photo: The agent calls
peek, which opens a live camera preview for the user to position an item.Interactive confirmation: The user presses space to take the photo or Escape to cancel.
Return image to agent: The captured photo is returned to the agent as an image content block.
Save photos locally: Images are automatically saved under
~/Pictures/Peek/.Show physical things: Useful for showing an agent a physical object, document, whiteboard, part number, or any visible item.
Adjustable parameters: Set
max_sideto control the longest edge of the returned image, ordeviceto choose a specific camera index.Flexible transport: Runs over stdio for local MCP clients, and can also run in HTTP mode for remote clients like ChatGPT.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@PeekTake a photo of this whiteboard so you can read the notes."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Peek
Let an AI agent take a photo with your camera.
Peek is an MCP server with one tool,
peek. When an agent calls it, a live camera preview opens. Position the
item, press space to capture, or Escape to cancel. The photo is
returned to the agent as an image and saved under ~/Pictures/Peek/.
Handy for showing an agent a physical object, a document, a whiteboard, a part number, or anything else it can't otherwise see.
Requirements
Python 3.12+
uv — used both to run the server and as the install mechanism below.
A camera. Developed and tested on macOS; should work anywhere OpenCV can open a camera, but the "keep window on top" behavior is macOS-specific.
Related MCP server: OpticMCP
Install
Peek isn't published to PyPI (the name's taken), so the easiest install is
to run it straight from GitHub with uv — no clone, no local checkout:
uvx --from git+https://github.com/davidray/peek.git peekuv caches the build after the first run, so subsequent launches are fast.
Every config below uses this form. If you'd rather work from a local clone
(e.g. to hack on it), see Local development.
The first capture triggers a camera permission prompt for whichever process launched the server (your terminal, or the app hosting your agent). On macOS, grant it under System Settings > Privacy & Security > Camera if you dismiss the prompt.
GitHub Copilot (VS Code)
Or run MCP: Add Server from the Command Palette, or add it from the command line:
code --add-mcp "{\"name\":\"peek\",\"command\":\"uvx\",\"args\":[\"--from\",\"git+https://github.com/davidray/peek.git\",\"peek\"]}"Or edit mcp.json yourself (MCP: Open User Configuration, or
.vscode/mcp.json for a single workspace):
{
"servers": {
"peek": {
"type": "stdio",
"command": "uvx",
"args": ["--from", "git+https://github.com/davidray/peek.git", "peek"]
}
}
}For the Copilot coding agent / Agent Host (which doesn't read
.vscode/mcp.json), use a workspace .mcp.json or user
~/.copilot/mcp-config.json with the same mcpServers shape shown under
Generic MCP clients below.
Claude
Claude Code:
claude mcp add --scope user peek -- uvx --from git+https://github.com/davidray/peek.git peekClaude Desktop: add this to your config
(~/Library/Application Support/Claude/claude_desktop_config.json on macOS):
{
"mcpServers": {
"peek": {
"command": "uvx",
"args": ["--from", "git+https://github.com/davidray/peek.git", "peek"]
}
}
}ChatGPT
ChatGPT's MCP connectors (Settings > Apps & Connectors, with Developer Mode enabled) only talk to a server over HTTPS — it can't launch a local stdio process the way Claude or VS Code can. To use Peek there:
Run Peek in HTTP mode on your machine:
uvx --from git+https://github.com/davidray/peek.git peek --transport http --port 8931Expose it with an HTTPS tunnel, e.g.
cloudflaredorngrok:cloudflared tunnel --url http://127.0.0.1:8931In ChatGPT, add a custom connector pointing at
https://<tunnel-host>/mcp.
Since this puts a local, unauthenticated server on a public URL for as long as the tunnel runs, only do this on a trusted network and shut the tunnel down when you're done.
Generic MCP clients
Most other clients (Cursor, Windsurf, etc.) use the same mcpServers shape:
{
"mcpServers": {
"peek": {
"command": "uvx",
"args": ["--from", "git+https://github.com/davidray/peek.git", "peek"]
}
}
}Local development
git clone git@github.com:davidray/peek.git
cd peek && uv syncThen point any of the configs above at your checkout instead of the git URL:
{
"mcpServers": {
"peek": {
"command": "uv",
"args": ["--directory", "/path/to/peek", "run", "peek"]
}
}
}Try it without an agent
uv run python -m peek.camera /tmp/test.jpgTool
peek(max_side: int = 1500, device: int = 0)
max_side: longest edge of the returned image in pixels (default 1500).device: camera index if you have more than one (default 0).
The server itself takes --transport {stdio,http} (default stdio), plus
--host/--port for HTTP mode. Stdio is what every desktop MCP client
uses; HTTP is only needed for clients (like ChatGPT above) that require a
reachable URL instead of a local process.
How it works
peek/server.py— the MCP server. Itspeektool shells out to the capture window and returns the resulting photo as an MCP image content block plus the saved path.peek/camera.py— the live preview, run as its own process since OpenCV's window/event loop needs the main thread.
Contributing
Issues and pull requests welcome. Keep it small: one tool, one job.
License
MIT — see LICENSE.
Available Tools
1 toolpeekA
Open a live camera preview so the user can position an item, then wait for them to press space to take the photo (or Escape to cancel).
Returns the photo as an image plus the path where it was saved.
Call this when you need to see a physical object, document, or scene.
Args:
max_side: longest edge in pixels for the returned image (default 1500).
device: camera index if the user has more than one (default 0).
| Name | Required | Description | Default |
|---|---|---|---|
| device | No | ||
| max_side | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden. It discloses the interactive nature ('wait for them to press space... or Escape to cancel'), the return value ('Returns the photo as an image plus the path where it was saved'), and the parameter defaults. It does not mention potential errors or permission issues, but the core blocking behavior is transparent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with the main behavior front-loaded, followed by return value and usage context, then parameter details. Every sentence adds necessary information, and the length is appropriate for a tool with no other documentation sources.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with two simple parameters, no annotations, and no output schema, the description covers the essential context: what the tool does, how to use it, what it returns, and parameter meanings. It could mention what happens on cancellation or return format, but these are minor gaps given the tool's simplicity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema provides no descriptions (0% coverage), so the description must fully define the parameters. It does: 'max_side: longest edge in pixels for the returned image' and 'device: camera index if the user has more than one.' Both meanings are clearly explained, including defaults, fully compensating for the schema's lack of detail.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's function: 'Open a live camera preview so the user can position an item, then wait for them to press space to take the photo (or Escape to cancel).' It uses specific verbs and identifies the resource (camera capture), making the purpose unmistakable even without siblings to contrast.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says 'Call this when you need to see a physical object, document, or scene,' providing clear context for when to use the tool. There are no sibling tools to compare against, and it does not mention exclusions, but the guidance is unambiguous for the intended use case.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
1 tool update
v0.1.0- First observed
peek
TDQS
Scored across 1 tool
With only one tool, there is no possibility of confusion or overlap between tools. The tool has a clear, single purpose of capturing a photo, so an agent cannot misselect among alternatives. This is a perfect disambiguation score by virtue of having a single tool.
The single tool name 'peek' is a clear verb that describes the action, and it is not inconsistent with any other tools since there are none. While there is no pattern to evaluate, the name is intuitive and aligns with the tool's purpose, so a slightly above-average score is appropriate.
The server has only one tool, which is at the lower boundary of what is considered reasonable. For a very narrow purpose like taking a photo, one tool might be sufficient, but it feels thin compared to more comprehensive servers. This aligns with the 'borderline' rating for 1-2 tools.
The tool fully covers its intended use case of capturing a photo, including options for resolution and camera selection. Minor gaps exist, such as no ability to list available cameras or adjust other settings, but these are not critical for the core functionality. The surface is complete for a single-action server.
Maintenance
Related MCP Connectors
AI image + video generation for agents: --flag prompt DSL, async generate/poll, x402 pay-per-use.
Turns a phone into a camera+Bluetooth remote so AI assistants can see and control any PC.
OCR, transcription, file extraction, and image generation for AI agents via MCP.
Generate images, GIFs, videos, and PDFs from HTML, URLs, or templates — from your AI agent.
Related MCP Servers
- AlicenseBqualityCmaintenanceEnables users to send live webcam images to Claude Desktop or other MCP clients, facilitating interaction through capturing images, screenshots, and providing a webcam view for visual input.212 npm121MIT
- AlicenseNot gradedqualityCmaintenanceProvides camera and vision tools for AI assistants to list available cameras, capture images from USB cameras, and save frames to disk for use with LLMs.4MIT
- AlicenseNot gradedqualityDmaintenanceAn MCP server that enables interaction with local camera devices to capture and process images. It allows LLMs to access video devices with configurable settings such as resolution, orientation, and image format.1MIT
- FlicenseNot gradedqualityCmaintenanceEnables AI agents to capture screenshots of windows (e.g., WeChat developer tools) and save them locally, allowing the agent to read the image directly and close the code-change-to-review loop without OSS or network.1-