Skip to content
On this site

Local MCP Server

Updated

Local MCP Server is coming in Wisply 1.11. Check the App Store for the version on your device.

Overview

Wisply for Mac can run a local Model Context Protocol (opens in a new tab) server, so AI tools on the same Mac, such as Claude Code, Cursor and Codex, can use your recordings as tools. Everything stays on your Mac: the server listens only on 127.0.0.1, every MCP request needs a token stored in your Keychain (only the identity check answers without one, and it returns proofs, never a token), and the server is off until you turn it on.

  • Transport: MCP Streamable HTTP (JSON responses), JSON-RPC 2.0, protocol 2025-06-18 (also accepts 2025-03-26 and 2024-11-05 clients).
  • Endpoint: http://127.0.0.1:51771/mcp. You can change the port in Settings.
  • Mac only. The iPhone and iPad apps don't run the server.

Turn it on

  1. Open Wisply → Settings → Integrations.
  2. In MCP Server, turn on Enable MCP server on this Mac.
  3. The status line shows the address it's listening on. Note the port.
  4. Click the eye icon (or Copy) next to Access token. This is the token your client sends. Regenerate… replaces it. For a tool that only needs to read, copy the Read-only connector token instead (see Tokens).
  5. Optional: turn on Allow agents to start and stop recordings. Leave it off unless you want connected tools to be able to capture audio. Reading works either way.

The server runs while Wisply is open and the switch is on. Quitting Wisply stops it. Nothing is exposed on your network.

Tokens

Each token is 32 random bytes, stored in your Keychain and checked in constant time. Any program on your Mac can open a connection to the port, so the token, not the connection, decides what a client can do.

Tokens
TokenPrefixReachesUse it for
Full-access token (Access token in Settings)wsp_…Every toolFor tools you trust to act in Wisply, such as Cursor, Claude Code or Codex.
Read-only connector tokenwspc_…list_memos, search_transcripts, get_live_transcript and get_action_itemsFor tools that only need to read.
Recording-control tokenwspr_…start_recording, stop_recording and propose_follow_upFor apps that only start and stop recordings and draft follow-ups. It can't list, search or read memos.

tools/list shows a token only the tools it reaches; calling any other tool returns JSON-RPC error -32003. Each token has its own Regenerate… button, so you can replace one without touching the others.

The Recording-control token is in the Wisply versions that have it, below Allow agents to start and stop recordings. Older versions show only the first two tokens.

Cursor

Add this to ~/.cursor/mcp.json (or a project's .cursor/mcp.json), with your token in place of wsp_…. Connect a client in Wisply's MCP Server settings copies it with your port and token filled in.

~/.cursor/mcp.json
{
  "mcpServers": {
    "wisply": {
      "url": "http://127.0.0.1:51771/mcp",
      "headers": {
        "Authorization": "Bearer wsp_…"
      }
    }
  }
}

Then open Cursor → Settings → MCP and check that wisply shows a green dot and its tools. If Cursor is already open:

  1. Save the snippet into ~/.cursor/mcp.json, merged with any mcpServers already there.
  2. In Settings → MCP, click the refresh icon next to wisply, or turn it off and on again. Wisply shows the client's name under its status line.
  3. Ask, for example, "List my latest Wisply memos." Tools that start or stop recordings go through Cursor's approval, and Wisply also refuses them unless recording control is on.

If you regenerate the token, update mcp.json and refresh the server entry again.

Claude Code

Terminal
claude mcp add --transport http wisply http://127.0.0.1:51771/mcp \
  --header "Authorization: Bearer wsp_…"

Then run /mcp in Claude Code to check the connection.

Codex

In ~/.codex/config.toml:

~/.codex/config.toml
[mcp_servers.wisply]
url = "http://127.0.0.1:51771/mcp"
bearer_token_env_var = "WISPLY_MCP_TOKEN"

Then set the token in the shell that launches Codex:

Terminal
export WISPLY_MCP_TOKEN="wsp_…"

Other clients

Any client that speaks MCP Streamable HTTP and can send an Authorization: Bearer header works. To try the server by hand:

Terminal
curl -s http://127.0.0.1:51771/mcp \
  -H "Authorization: Bearer wsp_…" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

Tools

Tools
Tool and argumentsSide effectsReturnsConnector tokenRecording-control token
list_memos (limit, offset)NoneNewest-first memos: id, title, timestamps, duration, pinned, summary preview, speaker countYesNo
search_transcripts (query, limit)NoneMemos whose title, summary or transcript contains the phrase, with an excerptYesNo
get_live_transcript (tail_words? (newer versions))NoneState, duration, transcript, word and speaker counts of the recording in progress, plus agent_recording_control (newer versions)YesNo
get_action_items (memo_id?)NoneAI action items and open questions for a memo (default: the newest with insights), plus action_bot_proposals, the Action Bot suggestions waiting for you this sessionYesNo
start_recordingCaptures audioWorks only while recording control is turned on in SettingsNoYes
stop_recordingEnds capture and saves the memoWorks only while recording control is turned on in SettingsNoYes
propose_follow_up (memo_id?, kind?, start?, duration_minutes?, title?)Adds a suggestion chip in Wisply's SidekickDrafts a calendar block, Zoom meeting or reminder from the memo and hands it to the Action Bot with a confirmation card. Returns status: proposed_pending_user_confirmation. Never writes anything itselfNoYes
get_action_proposal_status (proposal_id?)NoneStatus of one or all Action Bot proposals: proposed_pending_user_confirmation, committing, committed, undoing, undone, dismissed or failedNoNo
setup_claude (api_key?, request_consent?)Stores an Anthropic API key in the Keychain; asks Wisply to show its consent sheetYour Claude setup: whether a key is stored and the consent status (see Claude setup)NoNo

The Recording-control token column, tail_words and agent_recording_control apply only to the Wisply versions that have the recording-control token.

Every result carries a JSON text block and structuredContent. Results that contain recorded speech start with a notice telling the model to treat the transcript as data, not instructions.

Tool failures, such as bad arguments, recording control being off or an unknown memo, come back as isError: true results with a reason a person can read. Protocol problems, such as an unknown tool or malformed parameters, are JSON-RPC errors.

In the Wisply versions that have them, every isError result also carries structuredContent: { error, error_code, user_action? }. error_code is invalid_arguments, memo_not_found, no_memo_with_insights, recording_control_disabled, already_recording, not_recording, recording_failed, invalid_api_key_format, keychain_failure, consent_requires_user, action_bot_unavailable, action_kind_not_allowed, action_proposal_not_found, unavailable or internal. user_action is there when you have to do something in Wisply.

get_live_transcript takes tail_words (1 to 5000) to return only the last words of the transcript, which keeps polling cheap during long recordings; word_count still counts every word. Older Wisply versions ignore it and return the whole transcript.

Follow-ups need your OK

propose_follow_up doesn't create anything. It drafts a follow-up from the memo's action items and open questions (title, attendees, agenda, duration) and hands it to Wisply's Action Bot, which shows it as a chip in the Sidekick with its confirmation card open. You confirm it, and Wisply then adds it to Calendar, Reminders or Zoom with a receipt you can undo, or you dismiss it. A connected tool can't confirm or undo anything.

  • Action Bot suggestions must be on in Settings → Integrations → Action Bot. Otherwise the tool returns an error whose user_action says so.
  • The requested kind must be allowed there too: calendar (the default), task (Reminders) or zoom_meeting (needs Zoom connected and turned on).

A typical flow:

  1. Call propose_follow_up with a memo_id (and optionally kind, an ISO 8601 start, duration_minutes and title). It returns a proposal_id, status: "proposed_pending_user_confirmation" and a user_action to pass on.
  2. Tell the user the suggestion is waiting in the Sidekick.
  3. Call get_action_proposal_status with the proposal_id until it's committed (with committed_summary or external_url), dismissed, undone or failed (with failure_reason).

get_action_items also lists pending suggestions under action_bot_proposals, separate from the memo's action_items, so a tool can see what's already waiting before it suggests more.

With the recording-control token, which can't read memos, propose_follow_up adds the same chip but answers with a receipt instead of the draft: only proposal_id, kind, status, is_proposal_only and user_action. That token can't call get_action_proposal_status; you see the outcome in Wisply.

Claude setup from an agent

Wisply's Claude features need an Anthropic API key and your consent to cloud AI. A connected tool can store the key and ask for consent through setup_claude, but only you can grant consent, by choosing I Agree in Wisply's own consent sheet. A grant_consent argument is refused.

  1. Check: call setup_claude with no arguments. It reports api_key_present, consent_status (granted, pending_user_approval, declined or not_granted), consent_source and next_steps, and never shows anything in Wisply.
  2. Store a key: call setup_claude with api_key: "sk-ant-…". Wisply checks the sk-ant- format and stores the key in your Mac's Keychain; only Wisply sends it, and only to Anthropic. If consent isn't granted yet, Wisply comes to the front and shows the Cloud AI Data Consent sheet, naming the tool that asked. The tool gets consent_status: "pending_user_approval" and a user_action saying you decide in Wisply.
  3. Ask for consent only: call setup_claude with request_consent: true to show the same sheet without storing a key.
  4. Follow up: call setup_claude again. consent_status becomes granted (recorded as accepted by you after a request from that tool) or declined. Tools shouldn't ask again after a decline unless you tell them to. Settings → Integrations → Claude & Agents shows who asked and lets you revoke consent.
A new key replaces the one stored before. Only connect tools you trust with the full-access token.

Identity check (for client authors)

Any program can take Wisply's port while Wisply is closed. So before every call, a client can ask the server to prove it holds the client's token, without either side sending it. The request needs no Authorization header:

Identity check
GET /mcp/identity?nonce=<32-128 lowercase hex>      (no Authorization header)

200 {"server":"wisply","scheme":"wisply-mcp-identity-v1","port":51771,
     "nonce":"<nonce>","proofs":{"full":"<hex>","connector":"<hex>","recording":"<hex>"}}

key   = HMAC-SHA256(key: utf8(token), message: "wisply-mcp-identity-key-v1")
proof = hex(HMAC-SHA256(key: key, message: "wisply-mcp-identity-v1\n<port>\n<nonce>"))
  • The client checks the proof for the token it holds, in constant time: proofs.connector or proofs.full for the read-only or full-access token, proofs.recording for the recording-control token. The computation is the same for every token.
  • The port inside the proof stops a relay to a Wisply on another port, and the client's random nonce stops replays.
  • The endpoint keeps the loopback Host and Origin checks and answers 400 for a missing, repeated or malformed nonce. If Wisply can't read a token from the Keychain, the response leaves out that token's proof; with no token available it answers 503.
  • Wisply versions without the recording-control token answer without proofs.recording. Versions without the identity check answer 401 with WWW-Authenticate: Bearer realm="wisply-mcp"; a client should tell the user to update Wisply.

Security model

  • Loopback only. The server listens on 127.0.0.1, so nothing on your network can reach it.
  • Tokens. Every MCP request needs one of the tokens; only the identity check (/mcp/identity) answers without one, and it returns proofs, never a token. Any local program can open a connection, so the token is the boundary.
  • DNS-rebinding defense. Requests must carry a loopback Host, and an Origin header, if present, must be loopback too. Otherwise Wisply answers 403.
  • Your OK for side effects. start_recording and stop_recording are refused unless you turned on Allow agents to start and stop recordings. propose_follow_up only adds a suggestion, is refused unless Action Bot (and that kind) is on, and nothing is created until you confirm it in Wisply. setup_claude can store a key and ask for consent, but only your choice in the consent sheet grants it, and the grant names the tool that asked.
  • Transcripts are data. Results that contain recorded speech tell the model to treat it as data, not instructions.
  • Bounded requests. 1 MiB body limit, 16 KiB header limit, 30-second idle timeout and one request per connection.

Turn it off

Turn off Enable MCP server on this Mac in Settings → Integrations → MCP Server. Wisply stops answering MCP requests at once. Quitting Wisply stops the server too.

  • To cut off one tool without turning the server off, regenerate the token it uses and remove the Wisply entry from that tool's settings.
  • What a tool already read stays with that tool, and with its AI service, under their own terms.

Troubleshooting

Troubleshooting
SymptomFix
A client shows "connection refused"Wisply isn't open, or the server is off. Check the status line in Settings.
401 UnauthorizedThe token doesn't match. Copy it again, or regenerate it if you're unsure.
403 ForbiddenThe client used a host or origin that isn't loopback. Use 127.0.0.1 or localhost.
"Port is already in use"Change the port in Settings and update your client's configuration.
start_recording returns an error about recording controlTurn on Allow agents to start and stop recordings.
setup_claude keeps returning pending_user_approvalThe consent sheet is open in Wisply; answer it there. If you can't see it, click the Wisply window.
setup_claude returns an error that mentions grant_consentTools can't grant consent. Use request_consent: true and decide in Wisply.