tSIP MCP server plugin

Model Context Protocol (MCP) server for the tSIP softphone: exposes tSIP functions as tools for AI clients (Claude Code, Claude Desktop, IDE assistants, other MCP-capable agents).

Requires tSIP with plugin interface v2 (tSIP 0.3.16+). Written by Claude for Claude - what am I doing here?

Tools

Tool Description
get_app_info tSIP executable, profile directory, plugin interface
get_calls active calls: uid, direction, state, peer URI and name
get_registration configured accounts (accountId, name, user, server, current) and registration state
set_current_account select account used by default for outgoing calls / messages
get_history call history, newest first (limit, filter: all/incoming/outgoing/missed, search)
search_contacts phonebook search (query, limit): name, numbers, company, note
make_call start outgoing call (target: number or SIP URI; optional accountId, current account by default)
answer_call answer incoming call (uid optional: current call)
hangup_call hang up / reject call (uid, sipCode, reason optional)
wait_for_call wait (max 60 s) until call is answered / ended or new incoming call arrives
send_dtmf send DTMF digits in call (IVR navigation)
hold_call hold / resume call
transfer_call blind transfer; same checks as make_call (prefixes, confirmation)
list_audio_devices audio devices per module, configured devices
set_call_audio_input switch call input (microphone) device / back to configured
set_call_audio_output switch call output (speaker, headset) device / back to configured
play_audio_file play WAV file into call (file name only, from <profile>\audio or profile dir); optional wait for end and input restore
send_sip_request custom SIP request (OPTIONS, INFO, ...) to URI or within call, waits for reply
get_call_invite full text of received INVITE (or selected headers) for incoming call
get_audio_level peak level of received audio (0..32767)
wait_for_audio wait until other party speaks / becomes silent (e.g. end of IVR announcement)
mute_call mute / unmute microphone in call
set_sidetone sidetone on/off and level for call (hear transmitted audio, e.g. played file); not recorded
start_recording start call recording (settings from tSIP configuration)
send_message send text message (SIP MESSAGE); same checks as make_call
get_messages text message history with peer
get_settings global tSIP settings as JSON (optional section); account passwords as *** - only if allowConfigModification is true (default: false)
get_button_settings programmable buttons configuration (one by id, or all) - only if allowConfigModification is true
set_button_settings change one button by id, saved to the buttons file; restartRequired for account / BLF changes - only if allowConfigModification is true
set_settings merge JSON into global tSIP settings and save them; result lists changed sections and restartRequired - only if allowConfigModification is true (default: false)
run_script run Lua script - only if allowRunScript is true (default: false); returns return values and print() output, Lua errors as tool errors
get_log last lines of the tSIP log window (lines, default 50, max 1000); needs tSIP built with GetLogLines

get_history and search_contacts give the MCP client access to personal data (who called, phonebook); disable them with enabledTools if not wanted.

Planned (needs tSIP plugin interface additions): messages, BLF / presence state.

Prompts

Templates for common tasks (MCP prompts; in Claude Code available as /mcp__tsip__<name> commands). Listed only if tools they need are enabled.

Prompt Arguments Description
callback_last_missed - find last missed call and call back
missed_calls_summary period (optional, default today) missed calls grouped by caller
call_contact name find contact in phonebook and call
message_contact name, text find contact and send text message
call_and_navigate_ivr target, digits call, wait for answer, send DTMF

Transport and security

Risks to keep in mind: an AI agent (or content it reads, e.g. a web page with prompt injection) can try to make calls (toll fraud) or read call data (privacy). Keep confirmCalls enabled unless the agent is fully trusted.

Configuration

MCP.cfg (JSON) in tSIP profile directory (same directory as tSIP settings), created on first start. If tSIP does not report profile directory, file next to MCP.dll is used. Invalid file (e.g. JSON syntax error) is not overwritten - server is not started until the file is fixed or deleted.

Why profile directory and not phone\MCP.cfg next to the DLL (as v1 plugins do):

Plugin configured with older plugin version (phone\MCP.cfg): move the file to profile directory, otherwise new token is generated and MCP client has to be registered again.

{
   "port" : 8765,
   "token" : "<generated>",
   "confirmCalls" : true,
   "allowRunScript" : false,
   "activityStatus" : "all",
   "activityStatusSeconds" : 10,
   "allowPrefixes" : [],
   "denyPrefixes" : [],
   "enabledTools" : []
}

Settings can be changed in tSIP: Settings / Plugins, select MCP plugin, "Plugin settings..." - dialog saves the file and restarts the server (also: token regeneration, copying Claude Code command). File can be also edited manually - then disable and enable the plugin to apply.

Connecting clients

Claude Code:

claude mcp add --transport http tsip http://127.0.0.1:8765/mcp --header "Authorization: Bearer <token>"

Other clients: configure HTTP (Streamable HTTP) MCP server with the URL above and Authorization: Bearer <token> header.

Building

Code::Blocks 25.03 with bundled MinGW (GCC 14.2, 32-bit) - three equivalent ways:

Makefile and MCP.cbp must be kept in sync (source list, flags).

Output: bin/Release/MCP.dll - statically linked (no MinGW runtime DLLs), tSipPluginInit exported without stdcall decoration. Toolchain uses UCRT: Windows 10/11, or Windows 7/8.1 with UCRT update (KB2999226).

Testing without tSIP

build.bat testhost builds bin/Release/TestHost.exe, which loads MCP.dll like tSIP does, with fake Invoke() results for all methods and simulated call state events (see comment in test/TestHost.cpp).

Automated smoke test - starts TestHost in a temporary directory (own MCP.cfg, port 18765), calls all tools and prompts, checks results (Python 3, standard library only):

build.bat release
build.bat testhost
python test\smoke_test.py

Manual testing - current directory is reported as tSIP profile directory, so MCP.cfg with token is created there:

cd bin\Release
TestHost.exe MCP.dll 60

Then send requests, e.g.:

curl -H "Authorization: Bearer <token>" -H "Content-Type: application/json" ^
  -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"tools/list\"}" http://127.0.0.1:8765/mcp

Releases

Github: https://github.com/tomek-o/tSIP-plugin-mcp.

Back to tSIP softphone