sipgate-mcp 0.3.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,142 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.5.0 - 2026-08-30
4
+ - Add the final 32 tools for contacts, incoming blocklists, call/product
5
+ restrictions, history updates/deletes/CSV export, balance, portings,
6
+ account-wide sipgate.io settings, and webhook logs using the exact v2 paths,
7
+ verbs, query parameters, and request bodies.
8
+ - Permit account-wide contact, blacklist, balance, porting, sipgate.io, and
9
+ webhook-log reads in user scope. Require `confirm_account_wide: true` for
10
+ account-wide contact/blacklist writes, sipgate.io updates in user scope, and
11
+ every porting cancellation.
12
+ - Verify every single and bulk history mutation against owned history entries.
13
+ When user scope requests bulk deletion without IDs, enumerate both archived
14
+ and unarchived entries through owned connection IDs and send only those IDs;
15
+ never issue an unconstrained account-wide `DELETE /history`.
16
+ - Return `{before, after}` for all new mutations, including explicit
17
+ no-read-back/deletion notes. Mark contact CSV import, contact/history
18
+ deletion, and porting cancellation as destructive or irreversible.
19
+ - Add raw-text transport for contact/history CSV exports and explicit
20
+ 403/404-unavailable results for sipgate.io settings and webhook logs.
21
+ - Add 35 phoneline, voicemail/greeting, automated-recording, and faxline-
22
+ configuration tools covering every requested GET/POST/PUT/DELETE operation,
23
+ with exact v2 paths and payloads.
24
+ - Add phoneline detail, anonymous-call blocking, attached-device, and parallel-
25
+ forwarding reads/writes; enforce authenticated-user, owned-phoneline,
26
+ owned-device, and nested-forwarding boundaries.
27
+ - Add phoneline voicemail settings, greeting upload/activation/deletion,
28
+ transcription, global voicemail reads, and voicemail playback/recording call
29
+ sessions. Global results are filtered to voicemail IDs discovered under the
30
+ authenticated user's phonelines.
31
+ - Add automated call-recording announcement and per-extension settings. User
32
+ scope accepts settings only for an owned phoneline or faxline extension. The
33
+ account-global announcement has no user ownership link, so its read/create/
34
+ delete operations require administrator account scope.
35
+ - Add faxline creation, alias/deletion, caller-ID reads/writes, and tagline
36
+ updates with owned-faxline and owned-caller-number checks.
37
+ - Return explicit `phonelinesAvailable: false` / `changed: false` results for
38
+ phoneline-only tools when sipgate returns 403/404, without attempting a
39
+ mutation. An available but empty phoneline collection still denies access.
40
+ - Warn that voicemail call sessions and recording features may incur charges,
41
+ and that callers remain responsible for legally required recording consent.
42
+ - Expand read-only registration to 47 read tools and the full write-enabled
43
+ surface to 129 tools. Add one definition and backend endpoint test per new
44
+ tool plus foreign-resource and phoneline-less access-policy coverage.
45
+ - Add notification listing, creation, and deletion for call email/SMS, fax
46
+ email/SMS/report, incoming-SMS email, and voicemail email/SMS targets.
47
+ - Expose established calls and add hangup, hold, mute, recording, transfer,
48
+ DTMF, and announcement controls with before/after call snapshots.
49
+ - Add faxline and faxline-number reads plus chargeable fax send and resend
50
+ actions using sipgate's documented session payloads.
51
+ - Restrict user-scoped active calls to participants matching owned devices or
52
+ phone numbers, verify nested notification IDs before deletion, and verify
53
+ faxline ownership for reads, notifications, sends, and resends. Unknown or
54
+ unreadable ownership fails closed.
55
+ - Warn explicitly that fax transmission incurs charges and that call recording
56
+ can incur charges and requires participant consent in Germany.
57
+ - Keep a shared emergency address from leaking or rewriting other users' data:
58
+ user scope filters foreign numbers out of an address's number list and
59
+ refuses to edit an address that other users' numbers are attached to.
60
+ - Establish number ownership from the direct user-number endpoint as well as
61
+ routing, so quick dials that no phoneline or device routes can still be
62
+ updated and deleted by their owner.
63
+ - Page through every owned number when deciding ownership instead of stopping
64
+ after 1000.
65
+ - Redact PUK and ICCID values that arrive outside a credentials wrapper.
66
+ - Establish active-call ownership from the participant sipgate marks as the
67
+ call owner. Being the remote party of another user's call is not ownership,
68
+ and a call without a marked owner is denied.
69
+ - Verify that a resent fax belongs to the authenticated user, not just that the
70
+ faxline does.
71
+ - Accept national phone formats for transfer targets and fax recipients, which
72
+ the API documents as plain strings.
73
+ - Report the observed HTTP status when a phoneline or recording feature is
74
+ unavailable, so a denied token scope is no longer indistinguishable from an
75
+ account that simply has no phoneline layer.
76
+ - Say explicitly when a phoneline change was applied but only its read-back was
77
+ denied, instead of reporting the feature as unavailable.
78
+ - Accept an owned device as an automated-recording extension; sipgate documents
79
+ that feature for register endpoints, not only phonelines and faxlines.
80
+ - Refuse to delete an automated-recording greeting other than the one currently
81
+ configured.
82
+ - Refuse a history deletion whose entry list is present but empty. An empty
83
+ list serializes to no query parameter, which sipgate reads as "delete the
84
+ entire account history".
85
+ - Enforce the account-wide confirmation inside SipgateBackend as well, not only
86
+ at the access-control boundary, since the backend is exported on its own.
87
+ - Reject a bulk history update at sipgate's documented limit of 150 entries.
88
+ - Strip query strings from webhook log URLs, which carry their credentials
89
+ there as plain strings that key-based redaction cannot see.
90
+
91
+ - Add complete self-service tools for the requested sipgate v2 device surface:
92
+ device reads, updates and deletion; aliases; caller ID; local prefix; tariff
93
+ announcement; single-row display; external-device target/display settings;
94
+ password rotation; register/mobile/external device creation; and contingents.
95
+ - Add direct user-number reads plus quick-dial validation, creation, updates,
96
+ and deletion without routing these operations through phonelines.
97
+ - Add emergency-address listing, detail, number association, and updates for
98
+ assigning verified addresses to register devices.
99
+ - Enforce every new user-scoped resource target against owned devices, owned
100
+ numbers (including the device fallback on phoneline-less accounts), or
101
+ addresses associated with an owned device/number. Unknown ownership fails
102
+ closed with an access-policy error; administrator account scope retains its
103
+ broader behavior.
104
+ - Return `{before, after}` for all mutations, with explicit no-read-back notes
105
+ for creates and deletes. Redact credential containers and the one-time
106
+ password returned by device password rotation.
107
+ - Expand read-only mode from seven to 47 read tools; write tools are never
108
+ registered in read-only mode.
109
+ - Bump the package, CLI, and setup skill to version 0.5.0.
110
+
111
+ ## 0.4.0 - 2026-08-30
112
+
113
+ - Treat a 403/404 from the phoneline endpoints as "feature absent" instead of a
114
+ hard failure. Accounts without a phoneline layer keep their numbers directly
115
+ on a device, and a single failing phoneline lookup previously took down
116
+ `list_numbers`, `call_history`, `get_routing`, and `get_settings`.
117
+ - Resolve user numbers through the owning device when no phoneline layer
118
+ exists, and report the fallback via `source`, `phonelinesAvailable`, and
119
+ `numbersAvailable`.
120
+ - Scope user call history to device IDs when no phoneline IDs are available, so
121
+ history is no longer silently empty or denied.
122
+ - Accept an owned device as a routing destination in user scope. Numbers on
123
+ phoneline-less accounts point at a device, so the previous phoneline-only
124
+ check rejected every legitimate destination.
125
+ - Read every page of account numbers instead of a single 1000-number page, so
126
+ ownership checks and pagination stay correct on large accounts.
127
+ - Ask during interactive setup whether to register write tools instead of
128
+ silently defaulting to read-only. `--allow-writes` and the new `--read-only`
129
+ skip the question; a non-interactive run without either stays read-only.
130
+
131
+ ## 0.3.1 - 2026-08-30
132
+
133
+ - Fix Claude Code registration by using its unambiguous `mcp add-json` command
134
+ instead of the variadic `--env` parser.
135
+ - Clearly map macOS Keychain's generic `password data` prompts to sipgate's
136
+ PAT-ID and PAT labels.
137
+ - Reuse existing Keychain credentials on repeated setup runs and add
138
+ `--replace-credentials` for deliberate rotation.
139
+
3
140
  ## 0.3.0 - 2026-08-30
4
141
 
5
142
  - Add `sipgate-mcp setup` for interactive PAT storage in macOS Keychain.
package/README.md CHANGED
@@ -43,14 +43,25 @@ sipgate-mcp setup
43
43
 
44
44
  The setup stores the PAT token ID and token in macOS Keychain without placing
45
45
  either value in shell history or an MCP configuration file. It registers every
46
- installed supported client (Codex and Claude Code) in user/read-only mode.
46
+ installed supported client (Codex and Claude Code) in user scope. An
47
+ interactive setup asks whether to enable write tools; a non-interactive setup
48
+ without a mode flag registers read-only.
47
49
  Those clients start and stop the stdio server automatically; `sipgate-mcp` does
48
50
  not run as a daemon and does not need to be started manually.
49
51
 
50
52
  Use `sipgate-mcp setup --client codex` or `--client claude` to configure only
51
- one client. Add `--allow-writes` only when agent-initiated account changes are
52
- deliberately wanted. `--dry-run` prints the secret-free registration commands
53
- without changing the Keychain or client configuration.
53
+ one client. `--allow-writes` and `--read-only` pick the mode without being
54
+ asked; write tools let the assistant place calls, send SMS/faxes, and configure
55
+ routing, devices, phonelines, voicemail, greetings, recordings, faxlines,
56
+ contacts, blocklists, call restrictions, history, portings, and sipgate.io.
57
+ `--dry-run` prints the secret-free registration commands
58
+ without changing the Keychain or client configuration. Repeated setup runs
59
+ reuse existing Keychain credentials; use `--replace-credentials` only to rotate
60
+ the stored PAT-ID and PAT.
61
+
62
+ During first setup, macOS calls both secure inputs `password data`. The setup
63
+ labels the steps explicitly: enter the sipgate **PAT-ID** twice in step 1, then
64
+ the sipgate **PAT** twice in step 2. Input remains hidden while typing.
54
65
 
55
66
  Secure interactive storage currently supports macOS. Environment variables
56
67
  remain available for Linux, Windows, containers, CI, and password-manager
@@ -98,7 +109,7 @@ addition to sipgate's own user role and PAT scopes:
98
109
 
99
110
  | Value | Behavior |
100
111
  | --- | --- |
101
- | `user` (default) | Resolves the authenticated user through `/authorization/userinfo`; returns only that user and their assigned numbers; forces user-specific device, routing, and settings reads; constrains call history to owned connection IDs; and validates every write target against owned numbers, phonelines, or devices. |
112
+ | `user` (default) | Resolves the authenticated user through `/authorization/userinfo`; returns only that user and their assigned numbers, notifications, faxlines, phonelines, voicemails, greetings, and attached devices; forces user-specific device, routing, restriction, and settings reads; constrains history reads, exports, and mutations to owned connections/entries; and validates every write target against owned numbers, phonelines, nested voicemail/forwarding/greeting resources, devices, faxlines, notifications, or emergency addresses associated with an owned device/number. Account-wide contact, blacklist, porting-cancellation, and sipgate.io writes require `confirm_account_wide: true`; their reads are allowed and clearly labelled account-wide. |
102
113
  | `account` | Enables account-wide reads and writes. Startup fails unless `/users/{authenticatedUserId}` reports `admin: true`. Requires `users:read` for the administrator check. |
103
114
 
104
115
  Token scopes are permission ceilings, not role elevation. For example,
@@ -125,32 +136,165 @@ listed specific and parent scopes offered by the PAT UI when in doubt.
125
136
  | --- | --- | --- | --- |
126
137
  | `account_info` | Read | User: cached `/authorization/userinfo`; account: plus `GET /account` | Account: `account:read` (`userinfo` has no scope declaration in Swagger) |
127
138
  | `list_users` | Read | User: `GET /users/{self}`; account: `GET /users` | `users:read` |
128
- | `list_numbers` | Read | User: `GET /{self}/phonelines` and each phoneline's `/numbers`; account: `GET /numbers` | User: `phonelines:read`, `phonelines:numbers:read`; account: `numbers:read` |
139
+ | `list_numbers` | Read | User: own phonelines, or owned devices plus paginated `GET /numbers` when phonelines are unavailable; account: `GET /numbers` | User: `phonelines:read`, `phonelines:numbers:read`; fallback: `devices:read`, `numbers:read`; account: `numbers:read` |
129
140
  | `list_devices` | Read | User: `GET /{self}/devices`; account: `GET /users`, `GET /{userId}/devices` | `devices:read`; account also needs `users:read` when `user_id` is omitted |
141
+ | `get_device` | Read | Ownership `GET /{self}/devices`, then `GET /devices/{deviceId}` | `devices:read` |
142
+ | `get_device_caller_id` | Read | Device ownership read, then `GET /devices/{deviceId}/callerid` | `devices:read`, `devices:callerid:read` |
143
+ | `get_device_local_prefix` | Read | Device ownership read, then `GET /devices/{deviceId}/localprefix` | `devices:read`, `devices:localprefix:read` |
144
+ | `get_device_tariff_announcement` | Read | Device ownership read, then `GET /devices/{deviceId}/tariffannouncement` | `devices:read`, `devices:tariffannouncement:read` |
145
+ | `get_device_single_row_display` | Read | Device ownership read, then `GET /devices/{deviceId}/singlerowdisplay` | `devices:read`, `devices:singlerowdisplay:read` |
146
+ | `get_device_contingents` | Read | Device/user ownership reads, then `GET /{userId}/devices/{deviceId}/contingents` | `devices:read` |
147
+ | `list_user_numbers` | Read | `GET /{userId}/numbers`; this direct endpoint never uses phonelines | `numbers:read` |
148
+ | `validate_quick_dial` | Read | `GET /numbers/quickdial/validation/{quickDialNumber}` | `numbers:read` |
149
+ | `list_addresses` | Read | `GET /addresses`; user scope filters through owned device/number relationships | `addresses:read`; user ownership also needs `devices:read`, `numbers:read` and the applicable owned-number read scopes |
150
+ | `get_address` | Read | Address ownership reads, then `GET /addresses/{addressId}` | `addresses:read`; user ownership also needs `devices:read`, `numbers:read` and the applicable owned-number read scopes |
151
+ | `list_address_numbers` | Read | Address ownership reads, then `GET /addresses/{addressId}/numbers` | `numbers:read`, plus user ownership read scopes |
130
152
  | `get_routing` | Read | User: own phonelines, numbers, and forwardings; account: also `GET /numbers` and `GET /users` | `phonelines:read`, `phonelines:numbers:read`, `phonelines:forwardings:read`; account also needs `numbers:read` and, when `user_id` is omitted, `users:read` |
131
153
  | `call_history` | Read | User: ownership reads for own phonelines/devices, then filtered `GET /history`; account: `GET /history` | `history:read`; user also needs `phonelines:read`, `devices:read` |
154
+ | `list_calls` | Read | `GET /calls`; user scope filters calls to participants matching an owned device ID or phone number | `rtcm:read`; user ownership also needs `devices:read`, `numbers:read` and applicable owned-number scopes |
155
+ | `list_notifications` | Read | `GET /{userId}/notifications` | `notifications:read` |
156
+ | `list_faxlines` | Read | `GET /{userId}/faxlines` | `faxlines:read` |
157
+ | `list_faxline_numbers` | Read | User: faxline ownership read, then `GET /{userId}/faxlines/{faxlineId}/numbers`; account: direct `GET` | `faxlines:read`, `faxlines:numbers:read` |
158
+ | `get_phoneline` | Read | Owned-phoneline lookup, then `GET /{userId}/phonelines/{phonelineId}` | `phonelines:read` |
159
+ | `get_phoneline_block_anonymous` | Read | Owned-phoneline lookup, then `GET /{userId}/phonelines/{phonelineId}/blockanonymous` | `phonelines:read`, `phonelines:blockanonymous:read` |
160
+ | `list_phoneline_devices` | Read | Owned-phoneline/device filtering, then `GET /{userId}/phonelines/{phonelineId}/devices` | `phonelines:read`, `phonelines:devices:read`; user filtering also needs `devices:read` |
161
+ | `list_parallel_forwardings` | Read | Owned-phoneline lookup, then `GET /{userId}/phonelines/{phonelineId}/parallelforwardings` | `phonelines:read`, `phonelines:parallelforwardings:read` |
162
+ | `list_phoneline_voicemails` | Read | Owned-phoneline lookup, then `GET /{userId}/phonelines/{phonelineId}/voicemails` | `phonelines:read`, `phonelines:voicemails:read` |
163
+ | `list_voicemail_greetings` | Read | Owned phoneline/voicemail lookup, then `GET /{userId}/phonelines/{phonelineId}/voicemails/{voicemailId}/greetings` | `phonelines:read`, `phonelines:voicemails:read`, `phonelines:voicemails:greetings:read` |
164
+ | `list_voicemails` | Read | `GET /voicemails`; user scope filters by voicemail IDs discovered under owned phonelines | `voicemails:read`; user filtering also needs `phonelines:read`, `phonelines:voicemails:read` |
165
+ | `get_voicemail` | Read | Owned-voicemail lookup, then `GET /voicemails/{voicemailId}` | `voicemails:read`; user ownership also needs `phonelines:read`, `phonelines:voicemails:read` |
166
+ | `list_autorecording_greetings` | Read | Account scope only: `GET /autorecordings/greetings`; the account-global resource has no user ownership link | `autorecording:greeting:read`; sipgate also requires administrator privileges and activated call recording |
167
+ | `get_autorecording_settings` | Read | Owned phoneline/faxline extension lookup, then `GET /autorecordings/{extension}/settings` | `devices:read`; ownership also needs `phonelines:read`, `faxlines:read` |
168
+ | `get_faxline_caller_id` | Read | Owned-faxline lookup, then `GET /{userId}/faxlines/{faxlineId}/callerid` | `faxlines:read` |
169
+ | `create_phoneline` | Write/action | `POST /{userId}/phonelines`; 403/404 becomes a clean unavailable result | `phonelines:write` |
170
+ | `update_phoneline_alias` | Write | Owned-phoneline before/after reads and `PUT /{userId}/phonelines/{phonelineId}` | `phonelines:read`, `phonelines:write` |
171
+ | `delete_phoneline` | Write | Owned-phoneline before-state read and `DELETE /{userId}/phonelines/{phonelineId}` | `phonelines:read`, `phonelines:write` |
172
+ | `set_phoneline_block_anonymous` | Write | Owned-phoneline setting reads and `PUT /{userId}/phonelines/{phonelineId}/blockanonymous` | `phonelines:read`, `phonelines:blockanonymous:read`, `phonelines:blockanonymous:write` |
173
+ | `attach_device_to_phoneline` | Write/action | Owned phoneline/device reads, pre/post assignment reads, and `POST /{userId}/phonelines/{phonelineId}/devices` | `phonelines:read`, `phonelines:devices:read`, `phonelines:devices:write`, `devices:read` |
174
+ | `detach_device_from_phoneline` | Write | Owned phoneline/device reads, pre/post assignment reads, and `DELETE /{userId}/phonelines/{phonelineId}/devices/{deviceId}` | `phonelines:read`, `phonelines:devices:read`, `phonelines:devices:write`, `devices:read` |
175
+ | `create_parallel_forwarding` | Write/action | Owned-phoneline check, pre/post forwarding reads, and `POST /{userId}/phonelines/{phonelineId}/parallelforwardings` | `phonelines:read`, `phonelines:write`, `phonelines:parallelforwardings:read`, `phonelines:parallelforwardings:write` |
176
+ | `update_parallel_forwarding` | Write | Verify forwarding in the owned phoneline, pre/post reads, and `PUT /{userId}/phonelines/{phonelineId}/parallelforwardings/{parallelForwardingId}` | `phonelines:read`, `phonelines:write`, `phonelines:parallelforwardings:read`, `phonelines:parallelforwardings:write` |
177
+ | `delete_parallel_forwarding` | Write | Verify forwarding in the owned phoneline, pre/post reads, and `DELETE /{userId}/phonelines/{phonelineId}/parallelforwardings/{parallelForwardingId}` | `phonelines:read`, `phonelines:write`, `phonelines:parallelforwardings:read`, `phonelines:parallelforwardings:write` |
178
+ | `update_voicemail` | Write | Verify voicemail in the owned phoneline, pre/post voicemail reads, and `PUT /{userId}/phonelines/{phonelineId}/voicemails/{voicemailId}` | `phonelines:read`, `phonelines:write`, `phonelines:voicemails:read`, `phonelines:voicemails:write` |
179
+ | `create_voicemail_greeting` | Write/action | Verify owned voicemail, pre/post greeting reads, and `POST /{userId}/phonelines/{phonelineId}/voicemails/{voicemailId}/greetings` | `phonelines:read`, `phonelines:write`, `phonelines:voicemails:read`, `phonelines:voicemails:write`, `phonelines:voicemails:greetings:read`, `phonelines:voicemails:greetings:write` |
180
+ | `update_voicemail_greeting` | Write | Verify greeting under the owned voicemail, pre/post reads, and `PUT /{userId}/phonelines/{phonelineId}/voicemails/{voicemailId}/greetings/{greetingId}` | Same phoneline/voicemail/greeting read/write scopes as greeting creation |
181
+ | `delete_voicemail_greeting` | Write | Verify greeting under the owned voicemail, pre/post reads, and `DELETE /{userId}/phonelines/{phonelineId}/voicemails/{voicemailId}/greetings/{greetingId}` | Same phoneline/voicemail/greeting read/write scopes as greeting creation |
182
+ | `set_voicemail_transcription` | Write | Verify owned voicemail, pre/post voicemail reads, and `PUT /{userId}/phonelines/{phonelineId}/voicemails/{voicemailId}/transcriptions` | `phonelines:read`, `phonelines:write`, `phonelines:voicemails:read`, `phonelines:voicemails:write` |
183
+ | `play_voicemail` | Write/action | User: verify owned device and history/data entry; then `POST /sessions/voicemail/play` | `sessions:write`, `sessions:calls:write`; user ownership also needs `devices:read`, `history:read` and owned-connection scopes |
184
+ | `record_voicemail_greeting` | Write/action | User: verify owned device and target voicemail; then `POST /sessions/voicemail/recording` | `sessions:write`, `sessions:calls:write`; user ownership also needs `devices:read`, `phonelines:read`, `phonelines:voicemails:read` |
185
+ | `create_autorecording_greeting` | Write/action | Account scope only: pre/post `GET /autorecordings/greetings`, `POST /autorecordings/greetings` | `autorecording:greeting:read`, `autorecording:greeting:write`; sipgate requires administrator privileges and activated call recording |
186
+ | `delete_autorecording_greeting` | Write | Account scope only: before-state read, then `DELETE /autorecordings/greetings/{greetingId}` | `autorecording:greeting:read`, `autorecording:greeting:write`; sipgate requires administrator privileges and activated call recording |
187
+ | `set_autorecording_settings` | Write | Owned phoneline/faxline extension lookup, pre/post setting reads, and `PUT /autorecordings/{extension}/settings` | `devices:read`; ownership also needs `phonelines:read`, `faxlines:read` |
188
+ | `create_faxline` | Write/action | `POST /{userId}/faxlines` | `faxlines:write` |
189
+ | `update_faxline_alias` | Write | Owned-faxline pre/post list reads and `PUT /{userId}/faxlines/{faxlineId}` | `faxlines:read`, `faxlines:write` |
190
+ | `delete_faxline` | Write | Owned-faxline before-state read and `DELETE /{userId}/faxlines/{faxlineId}` | `faxlines:read`, `faxlines:write` |
191
+ | `set_faxline_caller_id` | Write | Owned faxline/number checks, pre/post caller-ID reads, and `PUT /{userId}/faxlines/{faxlineId}/callerid` | `faxlines:read`, `faxlines:write`, plus owned-number read scopes |
192
+ | `set_faxline_tagline` | Write | Owned-faxline pre/post list reads and `PUT /{userId}/faxlines/{faxlineId}/tagline` | `faxlines:read`, `faxlines:write` |
132
193
  | `get_settings` | Read | `GET /users[/userId]`, `GET /{userId}/devices`, `GET /{userId}/phonelines[/phonelineId]` | `users:read`, `devices:read`, `phonelines:read` |
194
+ | `list_contacts` | Read, account-wide | `GET /contacts` with phone, scope, and pagination filters | `contacts:read` |
195
+ | `get_contact` | Read, account-wide | `GET /contacts/{contactId}` | `contacts:read` |
196
+ | `list_internal_contacts` | Read, account-wide | Deprecated `GET /contacts/internal` compatibility route | `contacts:read` |
197
+ | `export_contacts_csv` | Read, account-wide | `GET /contacts/csv` and return CSV text | `contacts:read` |
198
+ | `get_contacts_vcard` | Read, account-wide | `GET /contacts/vcard` with structured-vCard filters | `contacts:read` |
199
+ | `create_contact` | Write/action, account-wide | `POST /contacts`; user scope requires `confirm_account_wide: true` | `contacts:write` |
200
+ | `update_contact` | Write, account-wide | Before/after `GET /contacts/{contactId}`, then `PUT` on the same path; confirmation required in user scope | `contacts:read`, `contacts:write` |
201
+ | `delete_contact` | Destructive write, account-wide | Before-state `GET`, then `DELETE /contacts/{contactid}`; confirmation required in user scope | `contacts:read`, `contacts:write` |
202
+ | `delete_contacts` | Destructive write, account-wide | Before-state contact reads, then `DELETE /contacts`; omitted filters delete all; confirmation required in user scope | `contacts:read`, `contacts:write` |
203
+ | `import_contacts_csv` | Destructive write/action, account-wide | Pre/post `GET /contacts`, then `POST /contacts/import/csv`; confirmation required in user scope | `contacts:read`, `contacts:write` |
204
+ | `put_contacts_vcard` | Write, account-wide | Pre/post `GET /contacts/vcard`, then `PUT /contacts/vcard`; supplied IDs are overwritten; confirmation required in user scope | `contacts:read`, `contacts:write` |
205
+ | `list_incoming_blacklist` | Read, account-wide | `GET /blacklist/incoming` | `blacklist:read` |
206
+ | `add_incoming_blacklist` | Write/action, account-wide | Pre/post blacklist reads, then `POST /blacklist/incoming`; confirmation required in user scope | `blacklist:read`, `blacklist:write` |
207
+ | `remove_incoming_blacklist` | Write, account-wide | Before-state blacklist read, then `DELETE /blacklist/incoming/{phoneNumber}`; confirmation required in user scope | `blacklist:read`, `blacklist:write` |
208
+ | `list_call_restrictions` | Read | User scope forces the authenticated ID in `GET /callrestrictions`; account scope accepts selected IDs | `callrestrictions:read` |
209
+ | `set_call_restriction` | Write | Pre/post restriction reads, then `POST /{authenticatedUserId}/callrestrictions/{restriction}` | `callrestrictions:read`, `callrestrictions:write` |
210
+ | `list_restrictions` | Read | `GET /restrictions`; user scope accepts only the authenticated user ID | Swagger declares the internal scope |
211
+ | `export_history` | Read | User: owned-connection-filtered `GET /history/export`; account: filtered or account-wide export | `history:read`; user ownership also needs `phonelines:read`, `devices:read` |
212
+ | `set_history_read` | Write | Owned-entry check, pre/post `GET /history/{entryId}`, then `PUT /history/{entryId}/read` | `history:read`, `history:write`; user ownership also needs connection read scopes |
213
+ | `set_history_note` | Write | Owned-entry check, pre/post entry reads, then `PUT /history/{entryId}/note` | `history:read`, `history:write`; user ownership also needs connection read scopes |
214
+ | `set_history_archive` | Write | Owned-entry check, pre/post entry reads, then `PUT /history/{entryId}/archive` | `history:read`, `history:write`; user ownership also needs connection read scopes |
215
+ | `update_history_entry` | Write | Owned-entry check, pre/post entry reads, then `PUT /history/{entryId}` | `history:read`, `history:write`; user ownership also needs connection read scopes |
216
+ | `delete_history_entry` | Destructive write | Owned-entry and before-state reads, then `DELETE /history/{entryId}` | `history:read`, `history:write`; user ownership also needs connection read scopes |
217
+ | `update_history_entries` | Write | Verify every entry, read before/after state, then `PUT /history` with fewer than 150 entries | `history:read`, `history:write`; user ownership also needs connection read scopes |
218
+ | `delete_history_entries` | Destructive write | `DELETE /history`; user scope expands omission to IDs enumerated through owned connection filters and never sends an unconstrained delete | `history:read`, `history:write`; user ownership also needs `phonelines:read`, `devices:read` |
219
+ | `get_balance` | Read, account-wide | `GET /balance` | `balance:read` |
220
+ | `list_portings` | Read, account-wide | `GET /portings` | `portings:read` |
221
+ | `get_porting` | Read, account-wide | `GET /portings/{portingId}` | `portings:read` |
222
+ | `cancel_porting` | Destructive write, account-wide | Before-state `GET`, then `DELETE /portings/{portingId}`; always requires `confirm_account_wide: true` | `portings:read`, `portings:write` |
223
+ | `get_sipgateio_settings` | Read, account-wide | `GET /settings/sipgateio`; 403/404 returns an unavailable result | `settings:read`, `settings:sipgateio:read` |
224
+ | `update_sipgateio_settings` | Write, account-wide | Pre/post settings reads, then `PUT /settings/sipgateio`; confirmation required in user scope | `settings:read`, `settings:write`, `settings:sipgateio:read`, `settings:sipgateio:write` |
225
+ | `list_webhook_logs` | Read, account-wide | `GET /log/webhooks`; 403/404 returns an unavailable result | `log:webhooks:read` |
133
226
  | `set_number_routing` | Write | User: pre/post reads through own phonelines; account: pre/post `GET /numbers`; all modes: `PUT /numbers/{numberId}` | `numbers:write`; user also needs `phonelines:read`, `phonelines:numbers:read`; account needs `numbers:read` |
134
227
  | `set_forwarding` | Write | User: phoneline ownership read; then pre/post forwarding reads and `PUT` | `phonelines:read`, `phonelines:write`, `phonelines:forwardings:read`, `phonelines:forwardings:write` |
135
228
  | `set_dnd` | Write | User: device ownership read; then pre/post `GET /devices/{deviceId}` and `PUT` | `devices:read`, `devices:write` |
229
+ | `update_device` | Write | Device and optional emergency-address ownership reads; pre/post `GET` plus `PUT /devices/{deviceId}` | `devices:read`, `devices:write`; address ownership may also need `numbers:read` and owned-number read scopes |
230
+ | `delete_device` | Write | Device ownership and before-state reads, then `DELETE /devices/{deviceId}` | `devices:read`, `devices:write` |
231
+ | `set_device_alias` | Write | Device ownership read; pre/post device reads and `PUT /devices/{deviceId}/alias` | `devices:read`, `devices:write` |
232
+ | `set_device_caller_id` | Write | Device and caller-number ownership reads; pre/post caller-ID reads and `PUT /devices/{deviceId}/callerid` | `devices:read`, `devices:write`, `devices:callerid:read`, `devices:callerid:write`, plus owned-number read scopes |
233
+ | `set_device_local_prefix` | Write | Device ownership read; pre/post setting reads and `PUT /devices/{deviceId}/localprefix` | `devices:read`, `devices:write`, `devices:localprefix:read`, `devices:localprefix:write` |
234
+ | `set_device_tariff_announcement` | Write | Device ownership read; pre/post setting reads and `PUT /devices/{deviceId}/tariffannouncement` | `devices:read`, `devices:write`, `devices:tariffannouncement:read`, `devices:tariffannouncement:write` |
235
+ | `set_device_single_row_display` | Write | Device ownership read; pre/post setting reads and `PUT /devices/{deviceId}/singlerowdisplay` | `devices:read`, `devices:write`, `devices:singlerowdisplay:read`, `devices:singlerowdisplay:write` |
236
+ | `set_external_device_target_number` | Write | Device ownership read; pre/post device reads and `PUT /devices/{deviceId}/external/targetnumber` | `devices:read`, `devices:write` |
237
+ | `set_external_device_incoming_call_display` | Write | Device ownership read; pre/post device reads and `PUT /devices/{deviceId}/external/incomingcalldisplay` | `devices:read`, `devices:write` |
238
+ | `change_device_password` | Write/action | Device ownership/before-state reads, then `POST /devices/{deviceId}/credentials/password`; the response is redacted | `devices:read`, `devices:write` |
239
+ | `create_register_device` | Write/action | `POST /{userId}/devices/register` | `devices:write` |
240
+ | `create_mobile_device` | Write/action | `POST /{userId}/devices/mobile` | `devices:write` |
241
+ | `create_external_device` | Write/action | `POST /{userId}/devices/external` | `devices:write` |
242
+ | `create_quick_dial` | Write/action | `POST /numbers/quickdial` | `numbers:write` |
243
+ | `update_quick_dial` | Write | Owned-number before/after reads and `PUT /numbers/quickdial/{quickdialId}` | `numbers:read`, `numbers:write`, plus applicable owned-number read scopes |
244
+ | `delete_quick_dial` | Write | Owned-number before-state read and `DELETE /numbers/quickdial/{numberId}` | `numbers:read`, `numbers:write`, plus applicable owned-number read scopes |
245
+ | `update_address` | Write | Address ownership and pre/post address reads, then `PUT /addresses/{addressId}` | `addresses:read`, `addresses:write`, plus user ownership read scopes |
136
246
  | `send_sms` | Write/action | `GET /{userId}/sms`, pre/post `GET /history`, `POST /sessions/sms` | `sms:read`, `history:read`, `sessions:write`, `sessions:sms:write` |
137
247
  | `initiate_call` | Write/action | User: device/number ownership reads, then `POST /sessions/calls`; account: pre/post `GET /calls` plus `POST` | `sessions:write`, `sessions:calls:write`; user also needs `devices:read`, `phonelines:read`, `phonelines:numbers:read`; account needs `rtcm:read` |
138
-
139
- Every write tool reads current state first and returns a JSON object with `before` and `after`. SMS history can update asynchronously, and `/calls` only contains established calls, so those action snapshots also include an acceptance/session marker.
248
+ | `create_call_email_notification` | Write/action | User: endpoint ownership reads; all modes: pre/post `GET /{userId}/notifications`, `POST /{userId}/notifications/call/email` | `notifications:read`, `notifications:write`; user also needs `devices:read` or `phonelines:read` |
249
+ | `create_call_sms_notification` | Write/action | User: endpoint ownership reads; all modes: pre/post notification reads, `POST /{userId}/notifications/call/sms` | `notifications:read`, `notifications:write`; user also needs `devices:read` or `phonelines:read` |
250
+ | `create_fax_email_notification` | Write/action | User: faxline ownership read; all modes: pre/post notification reads, `POST /{userId}/notifications/fax/email` | `notifications:read`, `notifications:write`; user also needs `faxlines:read` |
251
+ | `create_fax_sms_notification` | Write/action | User: faxline ownership read; all modes: pre/post notification reads, `POST /{userId}/notifications/fax/sms` | `notifications:read`, `notifications:write`; user also needs `faxlines:read` |
252
+ | `create_fax_report_notification` | Write/action | User: faxline ownership read; all modes: pre/post notification reads, `POST /{userId}/notifications/fax/report` | `notifications:read`, `notifications:write`; user also needs `faxlines:read` |
253
+ | `create_sms_email_notification` | Write/action | Pre/post notification reads, `POST /{userId}/notifications/sms/email` | `notifications:read`, `notifications:write` |
254
+ | `create_voicemail_email_notification` | Write/action | Pre/post notification reads, `POST /{userId}/notifications/voicemail/email` | `notifications:read`, `notifications:write` |
255
+ | `create_voicemail_sms_notification` | Write/action | Pre/post notification reads, `POST /{userId}/notifications/voicemail/sms` | `notifications:read`, `notifications:write` |
256
+ | `delete_notification` | Write | User: verify the nested ID in `GET /{userId}/notifications`; all modes: before/after notification reads and `DELETE /{userId}/notifications/{notificationId}` | `notifications:read`, `notifications:write` |
257
+ | `hangup_call` | Write | User: participant ownership read; all modes: before/after `GET /calls`, `DELETE /calls/{callId}` | `rtcm:read`, `rtcm:write`; user also needs owned-device/number read scopes |
258
+ | `set_call_hold` | Write | User: participant ownership read; before/after `GET /calls`, `PUT /calls/{callId}/hold` | `rtcm:read`, `rtcm:write`; user also needs owned-device/number read scopes |
259
+ | `set_call_muted` | Write | User: participant ownership read; before/after `GET /calls`, `PUT /calls/{callId}/muted` | `rtcm:read`, `rtcm:write`; user also needs owned-device/number read scopes |
260
+ | `set_call_recording` | Write | User: participant ownership read; before/after `GET /calls`, `PUT /calls/{callId}/recording` | `rtcm:read`, `rtcm:write`; user also needs owned-device/number read scopes |
261
+ | `transfer_call` | Write/action | User: call-participant and optional caller-ID ownership reads; before/after `GET /calls`, `POST /calls/{callId}/transfer` | `rtcm:read`, `rtcm:write`; user also needs owned-device/number read scopes |
262
+ | `send_call_dtmf` | Write/action | User: participant ownership read; before/after `GET /calls`, `POST /calls/{callId}/dtmf` | `rtcm:read`, `rtcm:write`; user also needs owned-device/number read scopes |
263
+ | `start_call_announcement` | Write/action | User: participant ownership read; before/after `GET /calls`, `POST /calls/{callId}/announcements` | `rtcm:read`, `rtcm:write`; user also needs owned-device/number read scopes |
264
+ | `send_fax` | Write/action | User: faxline ownership read; `POST /sessions/fax` | `sessions:write`, `sessions:fax:write`; user also needs `faxlines:read` |
265
+ | `resend_fax` | Write/action | User: required faxline ownership read; `POST /sessions/fax/resend` | `sessions:write`, `sessions:fax:write`; user also needs `faxlines:read` |
266
+
267
+ Every write tool returns a JSON object with `before` and `after`. Where a resource can be read, the tool reads current state first and reads it back after the change. Fax send/resend, voicemail playback/recording, and contact creation use `before: null` and return an explicit no-read-back note where sipgate exposes no synchronous identity/state; deletes return the previous state and a deletion marker. SMS history can update asynchronously, and `/calls` only contains established calls.
140
268
 
141
269
  ### Tool notes
142
270
 
143
271
  - `list_devices` resolves devices through users because the documented account-wide route is `GET /{userId}/devices`; the live v2 Swagger document does not define `GET /devices`.
144
- - User scope resolves assigned numbers through the authenticated user's phonelines and never calls account-wide `GET /users` or `GET /numbers` for read tools.
272
+ - `list_user_numbers` calls the documented direct `GET /{userId}/numbers` endpoint and never uses phonelines. Ownership checks retain the device-based fallback required by accounts without a phoneline layer.
273
+ - Every phoneline-dependent tool treats sipgate HTTP 403/404 as feature absence. On accounts where numbers hang directly from a device, reads return `phonelinesAvailable: false` and writes return `changed: false` without attempting the mutation. An available but empty phoneline list still denies every supplied phoneline ID.
274
+ - User scope establishes nested ownership from the documented collections: parallel forwardings under an owned phoneline, voicemails under an owned phoneline, greetings under an owned voicemail, and attached devices that are independently owned. Global `/voicemails` results are filtered to those discovered IDs.
275
+ - Voicemail playback requires an owned device and an owned history/data entry in user scope. The live Swagger request field is spelled `datadId`; the MCP exposes the clearer `data_id` and maps it without changing the API payload. Voicemail greeting recording requires an owned device and target voicemail in user scope.
276
+ - Automated recording settings accept only an extension found in the authenticated user's phonelines or faxlines. The automated-recording greeting is account-global and has no user ownership relationship, so its read/create/delete tools fail closed in user scope and require administrator account scope. sipgate additionally requires activated call recording.
277
+ - User scope never calls account-wide `GET /users`. It calls paginated account `GET /numbers` only for the device-based ownership fallback when phonelines are unavailable.
145
278
  - User-scoped number-routing snapshots are also resolved through owned phonelines, and user-scoped Click2Dial deliberately omits account-wide `/calls` snapshots.
279
+ - User-scoped `list_calls` and every live-call mutation read the account-wide `/calls` feed but expose or operate on a call only when at least one participant's `participantId` matches an owned device or `phoneNumber` matches an owned phone number. A missing, unknown, or unreadable match fails closed. sipgate's Swagger does not expose a separate call-owner user or device field.
280
+ - Notification IDs live inside the nested email/SMS/report target arrays returned by `GET /{userId}/notifications`; deletion verifies that nested ID before sending the request. Call-notification endpoints are checked against owned devices/phonelines, and fax notifications against owned faxlines.
281
+ - Fax send and resend actions incur charges. In user scope `resend_fax` requires `faxline_id` even though sipgate marks it optional, because omitting it leaves no documented ownership relationship that can be verified before the chargeable action.
282
+ - Contacts and the incoming blacklist are account-wide sipgate resources. Their reads remain available in user scope, but every write requires `confirm_account_wide: true`; CSV import and contact/history deletion are described as destructive. Porting cancellation always requires the same explicit confirmation and is irreversible through v2.
283
+ - Every single-entry history mutation verifies `connectionIds` against the authenticated user's owned device/phoneline IDs. User-scoped bulk updates verify every entry. An omitted ID list on bulk deletion is expanded by paging both archived and unarchived history through owned connection filters, then deleting only those IDs; an unconstrained `DELETE /history` is never sent in user scope.
284
+ - `set_call_restriction` never accepts a user ID: the backend resolves `/authorization/userinfo` and posts only to `/{authenticatedUserId}/callrestrictions/{restriction}`. `list_call_restrictions` and `list_restrictions` reject foreign users in user scope.
285
+ - Balance, portings, global sipgate.io settings, and webhook logs are account-wide reads that remain visible in user scope. Updating global sipgate.io settings requires account-wide confirmation in user scope. sipgate.io settings/log endpoints translate 403/404 into explicit unavailable results.
286
+ - Call and automated recording can incur charges and are legally sensitive. In Germany the caller is responsible for obtaining consent from every participant; changing or disabling an announcement does not remove that responsibility. Voicemail playback/recording initiates a call and may also incur charges.
287
+ - Address IDs are exposed as integers because sipgate declares every address path parameter as `int32`. In user scope an address is visible or mutable only when an owned device references it, an owned number contains its `addressId`, or `/addresses/{addressId}/numbers` contains an owned number.
288
+ - Device creation can affect billing, and changing an address can deactivate associated telephone numbers depending on country. Every write-tool description advertises the account change and potential charges.
289
+ - Device password rotation intentionally redacts the complete credential container, including sipgate's one-time password response.
146
290
  - Number routing uses sipgate's documented `endpointId`. Obtain existing IDs from the read tools; a phoneline ID such as `p0` is the documented example.
147
291
  - `set_forwarding` replaces the complete phoneline forwarding list. Pass `forwardings: []` to remove all forwardings. A `timeout` of `0` represents immediate forwarding.
148
292
  - `send_sms` refuses to post unless `GET /{userId}/sms` returns the requested (or first available) SMS extension.
149
- - sipgate documents `POST /sessions/calls` as the classic-PBX Click2Dial route. The API documentation points Neo PBX accounts to `/calls`; supporting that distinct call workflow is left for a future compatibility pass.
293
+ - sipgate documents `POST /sessions/calls` as the classic-PBX Click2Dial route. Live established-call reads and controls use `/calls`; starting a new Neo PBX call through the separate `POST /calls` shape is outside this batch.
150
294
 
151
295
  ## Read-only mode
152
296
 
153
- Set `SIPGATE_MCP_READONLY=1` to register only the seven read tools. Write tools are absent from `tools/list`, rather than merely failing when called.
297
+ Set `SIPGATE_MCP_READONLY=1` to register only the 47 read tools. Write tools are absent from `tools/list`, rather than merely failing when called.
154
298
 
155
299
  ```bash
156
300
  export SIPGATE_MCP_READONLY=1
@@ -257,7 +401,11 @@ MCP stdio server
257
401
  - `sipgate-mcp setup` delegates secret entry directly to the macOS Keychain
258
402
  prompt. Secret values are never passed as command-line arguments and are not
259
403
  written to Codex or Claude configuration.
260
- - User scope is the default and validates user IDs plus number, phoneline, device, call, and history ownership before delegation.
404
+ - User scope is the default and validates user IDs plus number, phoneline,
405
+ nested voicemail/greeting/forwarding, device, faxline, call, recording-
406
+ extension, and history ownership before delegation. Bulk history deletion is
407
+ expanded to owned entry IDs, and account-wide writes require explicit
408
+ confirmation where documented above.
261
409
  - Account scope fails startup unless the authenticated sipgate user reports `admin: true`.
262
410
  - The Basic Auth header exists only in memory and is sent only to the fixed sipgate API base URL.
263
411
  - API error bodies are discarded. User-facing errors never include request headers, response bodies, or credentials.
@@ -289,7 +437,7 @@ Maintainer setup and the one-time first-publish procedure are documented in
289
437
 
290
438
  ## API provenance and limitations
291
439
 
292
- The endpoint paths, query parameters, request bodies, response models, and scope names were checked against sipgate's live public [REST API v2 Swagger document](https://api.sipgate.com/v2/swagger.json) and [Swagger UI](https://api.sipgate.com/v2/doc) on 2026-08-29. PAT Basic Auth was checked against sipgate's public authentication guide. No authenticated production account was available during development, so real-account behavior remains to be confirmed with the smoke test above—especially product-specific availability, eventual history updates, and classic versus Neo PBX calling.
440
+ The endpoint paths, query parameters, request bodies, response models, and scope names were checked against sipgate's live public [REST API v2 Swagger document](https://api.sipgate.com/v2/swagger.json) and [Swagger UI](https://api.sipgate.com/v2/doc) on 2026-08-30. PAT Basic Auth was checked against sipgate's public authentication guide. No authenticated production account was available during development, so real-account behavior remains to be confirmed with the smoke test above—especially product-specific availability, eventual history updates, and classic versus Neo PBX calling.
293
441
 
294
442
  ## Roadmap
295
443
 
package/SKILL.md CHANGED
@@ -2,7 +2,7 @@
2
2
  name: sipgate-mcp
3
3
  description: Install and securely configure the sipgate MCP server when a user asks to set up or connect a sipgate account to Codex or Claude. Do not use for ordinary sipgate product questions.
4
4
  metadata:
5
- version: "0.3.0"
5
+ version: "0.5.0"
6
6
  ---
7
7
 
8
8
  # Set up sipgate MCP
@@ -10,19 +10,19 @@ metadata:
10
10
  Install the matching CLI version with one available package manager:
11
11
 
12
12
  ```bash
13
- vp install -g sipgate-mcp@0.3.0
13
+ vp install -g sipgate-mcp@0.5.0
14
14
  ```
15
15
 
16
16
  ```bash
17
- npm install -g sipgate-mcp@0.3.0
17
+ npm install -g sipgate-mcp@0.5.0
18
18
  ```
19
19
 
20
20
  ```bash
21
- pnpm add -g sipgate-mcp@0.3.0
21
+ pnpm add -g sipgate-mcp@0.5.0
22
22
  ```
23
23
 
24
24
  Run only one install command. Confirm that `sipgate-mcp --version` reports
25
- `0.3.0` before continuing.
25
+ `0.5.0` before continuing.
26
26
 
27
27
  ## Security boundary
28
28
 
@@ -32,8 +32,36 @@ Run only one install command. Confirm that `sipgate-mcp --version` reports
32
32
  files, logs, or issue reports.
33
33
  - The local server uses a sipgate Personal Access Token. A sipgate OAuth API
34
34
  client ID and secret are not substitutes for this local setup.
35
- - Keep the first setup user-scoped and read-only. Do not enable write tools or
35
+ - Keep setup user-scoped. Let the setup prompt decide read-only versus write
36
+ tools, and do not pass `--allow-writes` on the user's behalf. Never enable
36
37
  account-wide administrator access without an explicit user request.
38
+ - The automated-recording greeting is account-global and intentionally fails
39
+ closed in user scope; its read/create/delete tools require explicitly
40
+ requested administrator account scope.
41
+ - User scope remains the resource boundary for write tools: device IDs,
42
+ phone-number IDs, emergency-address IDs, notification IDs, live-call
43
+ participants, phonelines, nested parallel forwardings, voicemails and
44
+ greetings, attached devices, faxlines, and automated-recording extensions
45
+ are checked against the authenticated user's ownership before account
46
+ changes are sent.
47
+ - Contacts and the incoming blacklist are account-wide resources. In user
48
+ scope, never call one of their write tools unless the user explicitly agrees
49
+ to the account-wide effect and the call includes
50
+ `confirm_account_wide: true`. The same confirmation is always required to
51
+ cancel a number porting, and user-scoped sipgate.io settings updates require
52
+ it as well.
53
+ - History writes are limited to owned entries. An omitted ID list for bulk
54
+ deletion is expanded to entries from owned connection IDs; never work around
55
+ that boundary with account scope unless the user explicitly requested
56
+ administrator-wide access.
57
+ - Never display device credentials. Password rotation deliberately redacts the
58
+ one-time password returned by sipgate.
59
+ - Fax send/resend and call-initiating voicemail playback/recording actions may
60
+ incur charges. Call and automated recording are legally sensitive; in
61
+ Germany the caller is responsible for obtaining every participant's consent,
62
+ even when the recording announcement is off.
63
+ - Contact CSV imports and history/contact deletions are destructive. Cancelling
64
+ a number porting is irreversible through the v2 API.
37
65
  - Do not remove or replace an existing MCP configuration without the user's
38
66
  approval.
39
67
 
@@ -54,8 +82,30 @@ sipgate-mcp setup --client claude
54
82
 
55
83
  Omit `--client` only when both installed clients should be configured. The
56
84
  setup delegates PAT entry directly to macOS Keychain and registers a
57
- user-scoped, read-only stdio server. The client starts and stops that process;
58
- do not launch `sipgate-mcp` as a daemon.
85
+ user-scoped stdio server. Its interactive prompt asks whether write tools should
86
+ be enabled; do not answer that choice on the user's behalf. The client starts
87
+ and stops that process, so do not launch `sipgate-mcp` as a daemon.
88
+
89
+ Version 0.5.0 adds user-scoped device, quick-dial, user-number, emergency-
90
+ address, notification, live-call-control, phoneline, voicemail/greeting,
91
+ automated-recording, fax, contact, blacklist, restriction, history-management,
92
+ porting, balance, and sipgate.io self-service. It supports accounts without
93
+ phonelines: direct number reads use `/{userId}/numbers`, ownership checks retain
94
+ the device-based number fallback, and phoneline-only tools return an explicit
95
+ unavailable result instead of surfacing sipgate's 403. Active calls are
96
+ filtered by participants matching owned devices or numbers; nested voicemail,
97
+ greeting, forwarding, attached-device, faxline, and recording-extension IDs
98
+ are verified before use. History updates/deletes and exports are constrained to
99
+ owned connection IDs; account-wide contacts/blacklist writes and sipgate.io
100
+ updates require explicit confirmation in user scope, as does porting
101
+ cancellation. Device/faxline/phoneline creation, fax transmission, call
102
+ sessions, recording, and other writes may incur charges or carry legal
103
+ consequences, and address changes can deactivate associated numbers depending
104
+ on country.
105
+
106
+ When credentials already exist in Keychain, setup reuses them without another
107
+ prompt. Use `--replace-credentials` only when the user explicitly wants to
108
+ rotate or replace the stored PAT-ID and PAT.
59
109
 
60
110
  If the Keychain prompt cannot be presented in the current environment, ask the
61
111
  user to run the setup command in their local interactive terminal. Do not ask