Meetings for your AI agent
Ask Claude, Cursor, or any MCP client about your meetings: what a customer asked for, which action items you agreed to, what was said on Tuesday. Your agent searches and reads your ViewFraming summaries and transcripts directly, so you never paste or share them by hand.
Get started
- Turn on meeting syncIn the ViewFraming app, open Settings and turn on Sync meetings for AI agents. Meetings you finish from then on are uploaded, and you can upload the last 7 days.
- Create an API keySign in at viewframing.com/account#api-keys and create a key. Copy it right away: it is shown only once.
- Add ViewFraming to your agentPaste the key into your agent's settings, as shown below for each client.
Connect your agent
ViewFraming is a remote MCP server. Every client needs the same two things:
| Server URL | https://api.viewframing.com/mcp |
|---|---|
| Header | Authorization: Bearer vf_key_… |
Run once in a terminal, with your key in place of vf_key_YOUR_KEY:
claude mcp add --transport http viewframing https://api.viewframing.com/mcp \
--header "Authorization: Bearer vf_key_YOUR_KEY"Add --scope user to use it in every project. Check it with /mcp inside Claude Code.
Open Settings, then Developer, then Edit Config, and add this to claude_desktop_config.json. It uses mcp-remote, which needs Node.js. Restart Claude Desktop afterwards.
{
"mcpServers": {
"viewframing": {
"command": "npx",
"args": [
"-y", "mcp-remote", "https://api.viewframing.com/mcp",
"--header", "Authorization:${VIEWFRAMING_AUTH}"
],
"env": { "VIEWFRAMING_AUTH": "Bearer vf_key_YOUR_KEY" }
}
}
}Add this to ~/.cursor/mcp.json for every project, or .cursor/mcp.json for one:
{
"mcpServers": {
"viewframing": {
"url": "https://api.viewframing.com/mcp",
"headers": { "Authorization": "Bearer vf_key_YOUR_KEY" }
}
}
}Add this to .vscode/mcp.json. VS Code asks for the key the first time and stores it securely, so the key never sits in the file.
{
"inputs": [
{
"type": "promptString",
"id": "viewframing-key",
"description": "ViewFraming API key",
"password": true
}
],
"servers": {
"viewframing": {
"type": "http",
"url": "https://api.viewframing.com/mcp",
"headers": { "Authorization": "Bearer ${input:viewframing-key}" }
}
}
}Try it
Once connected, just ask:
- "What did Acme push back on in this week's pricing call?"
- "List every action item I agreed to since Monday."
- "Summarize my interviews from last week and what I could answer better."
Tools
The server has two read-only tools. Your agent picks them on its own; you only need these details to call them yourself.
list_meetings
Your meetings, newest first, with an optional full-text search.
| Argument | Type | Description |
|---|---|---|
query | string | Words to match in titles, summaries and transcripts. Supports "quoted phrases", OR, and -excluded words. Up to 200 characters. |
from | RFC 3339 time | Only meetings that started at or after this time. |
to | RFC 3339 time | Only meetings that started before this time. |
limit | integer | 1 to 50. Default 20. |
cursor | string | The next_cursor of the previous page. |
Each item has id, title, mode, started_at, ended_at, expires_at, and summary, the first 500 characters of the meeting summary. With a query, each item also has a snippet with the matches in **bold**. next_cursor is null on the last page.
{
"meetings": [
{
"id": "6f1c2a9e-4b7d-4e15-9a3c-0d2f8b6e1a44",
"title": "Pricing sync with Acme",
"mode": "sales_calls",
"started_at": "2026-10-27T15:00:00Z",
"ended_at": "2026-10-27T15:32:00Z",
"expires_at": "2026-11-03T15:40:12Z",
"summary": "Acme wants a volume discount before renewing...",
"snippet": "We need a **discount** on the enterprise plan before Friday"
}
],
"next_cursor": null
}get_meeting
One meeting in full.
| Argument | Type | Description |
|---|---|---|
id | string, required | A meeting id from list_meetings. |
include_transcript | boolean | Default true. Set false for the summary sections only. |
The result has title, mode, started_at, ended_at, and sections. Each section has a heading, a kind such as summary or action_items, and a body or items. It also has the transcript as turns with speaker, role (me, others, unknown), and text. Transcripts over 200 KB of text are cut at a whole turn, with transcript_truncated: true.
{
"id": "6f1c2a9e-4b7d-4e15-9a3c-0d2f8b6e1a44",
"title": "Pricing sync with Acme",
"mode": "sales_calls",
"started_at": "2026-10-27T15:00:00Z",
"ended_at": "2026-10-27T15:32:00Z",
"expires_at": "2026-11-03T15:40:12Z",
"sections": [
{ "heading": "Summary", "kind": "summary", "body": "Acme wants a volume discount..." },
{ "heading": "Action items", "kind": "action_items", "items": ["Send revised quote by Thursday"] }
],
"transcript": [
{ "speaker": "Me", "role": "me", "text": "Thanks for making time. Where did you land on the renewal?" },
{ "speaker": "Others", "role": "others", "text": "We need a discount on the enterprise plan before Friday." }
],
"transcript_truncated": false
}Call it over HTTP
MCP is JSON-RPC 2.0 over HTTPS, so you can call the tools from a script without an MCP client. Send one JSON-RPC message per POST; the answer is plain JSON.
curl https://api.viewframing.com/mcp \
-H "Authorization: Bearer $VIEWFRAMING_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "list_meetings",
"arguments": { "query": "pricing", "limit": 5 }
}
}'The tool's output is in result.structuredContent, and the same JSON is in result.content[0].text:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [{ "type": "text", "text": "{\"meetings\":[...],\"next_cursor\":null}" }],
"structuredContent": { "meetings": [ ... ], "next_cursor": null },
"isError": false,
"resultType": "complete"
}
}The server is stateless: no session id, no event stream. It also answers initialize (protocol versions 2025-03-26 to 2025-11-25), server/discover (2026-07-28), tools/list, and ping.
API keys
- Create, view, and revoke keys at viewframing.com/account#api-keys. You can have up to 5 at a time, for example one per device or agent.
- Keys start with
vf_key_. The full key is shown once when you create it. Afterwards the list shows its first characters and when it was last used. - Revoking a key stops it at once.
- A key can only read your meetings through
/mcp. It can't sign in, change your account, or upload anything. - Keep keys out of shared repositories and screenshots. If one leaks, revoke it and create a new one.
Limits and errors
| Limit | Value |
|---|---|
| Requests | 60 per minute per account, across all keys and the app's uploads |
| Meeting retention | 7 days from first upload |
| Synced meetings | 300 at a time |
| Results per page | 50 |
| Transcript per meeting | 200 KB of text |
| Answer | Meaning |
|---|---|
401 | Missing, mistyped, or revoked key. |
403 | The request came from a web page (it had an Origin header), or the account is disabled. |
429 | Over the rate limit. Wait the number of seconds in Retry-After. |
plan_required | A tool error (isError: true) when the account isn't on Pro or Lifetime. Connecting still works. |
not_found | A tool error: no meeting with that id, or it has expired. |
-32602 | JSON-RPC invalid params, such as a bad limit, time, or cursor. The message says which. |
Your data
- Sync is off until you turn it on. Only meetings on a Pro or Lifetime account are uploaded.
- A synced meeting holds its title, mode, times, summary sections (summary, action items, and others), and transcript. Audio and photos are never uploaded.
- Each meeting is deleted 7 days after its first upload. Turn sync off or delete a meeting in the app to remove it sooner.
- Only your own keys can read your meetings. ViewFraming runs no AI over them for this feature: your agent does the reading.
- Transcripts contain what other people said. Agents should treat meeting text as information, never as instructions. The server tells them so, but check what an agent does with it.
Questions: hello@viewframing.com.