sipgate-mcp 0.1.0 → 0.3.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 +29 -0
- package/README.md +125 -34
- package/SKILL.md +87 -0
- package/dist/backend/access-controlled-backend.d.ts +57 -0
- package/dist/backend/access-controlled-backend.d.ts.map +1 -0
- package/dist/backend/access-controlled-backend.js +227 -0
- package/dist/backend/access-controlled-backend.js.map +1 -0
- package/dist/backend/sipgate-backend.d.ts +13 -1
- package/dist/backend/sipgate-backend.d.ts.map +1 -1
- package/dist/backend/sipgate-backend.js +101 -10
- package/dist/backend/sipgate-backend.js.map +1 -1
- package/dist/backend/telephony-backend.d.ts +16 -0
- package/dist/backend/telephony-backend.d.ts.map +1 -1
- package/dist/config.d.ts +4 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +19 -5
- package/dist/config.js.map +1 -1
- package/dist/credentials.d.ts +13 -0
- package/dist/credentials.d.ts.map +1 -0
- package/dist/credentials.js +57 -0
- package/dist/credentials.js.map +1 -0
- package/dist/index.d.ts +6 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +38 -4
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts +2 -2
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +8 -3
- package/dist/server.js.map +1 -1
- package/dist/setup.d.ts +17 -0
- package/dist/setup.d.ts.map +1 -0
- package/dist/setup.js +152 -0
- package/dist/setup.js.map +1 -0
- package/dist/tools/definitions.d.ts +2 -2
- package/dist/tools/definitions.d.ts.map +1 -1
- package/dist/tools/definitions.js +53 -18
- package/dist/tools/definitions.js.map +1 -1
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +2 -0
- package/dist/version.js.map +1 -0
- package/package.json +3 -1
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.3.0 - 2026-08-30
|
|
4
|
+
|
|
5
|
+
- Add `sipgate-mcp setup` for interactive PAT storage in macOS Keychain.
|
|
6
|
+
- Register installed Codex and Claude Code clients with a secret-free launch
|
|
7
|
+
command, user scope, and read-only mode by default.
|
|
8
|
+
- Load Keychain credentials automatically when environment credentials are
|
|
9
|
+
absent, while keeping environment variables as an explicit override.
|
|
10
|
+
- Add setup dry-run and opt-in write-mode flags.
|
|
11
|
+
- Add a versioned agent skill and README bootstrap link for guided setup.
|
|
12
|
+
- Add `sipgate-mcp --version` and verify that CLI, package, and skill versions
|
|
13
|
+
remain synchronized.
|
|
14
|
+
|
|
15
|
+
## 0.2.0 - 2026-08-30
|
|
16
|
+
|
|
17
|
+
- Default to MCP-level user scope resolved from sipgate's authenticated user.
|
|
18
|
+
- Restrict user-scoped users, numbers, devices, phonelines, settings, and call
|
|
19
|
+
history to the authenticated user's resources.
|
|
20
|
+
- Validate user-scoped write targets and outbound caller identities before
|
|
21
|
+
sending changes or chargeable actions to sipgate.
|
|
22
|
+
- Avoid account-wide number and active-call snapshots in user-scoped actions.
|
|
23
|
+
- Add explicit account scope that requires a verified sipgate administrator.
|
|
24
|
+
- Advertise active scope and read-only behavior through MCP server instructions.
|
|
25
|
+
|
|
26
|
+
## 0.1.0 - 2026-08-30
|
|
27
|
+
|
|
28
|
+
- Initial local stdio MCP server with focused sipgate read and write tools.
|
|
29
|
+
- Personal Access Token authentication and optional read-only mode.
|
package/README.md
CHANGED
|
@@ -2,18 +2,32 @@
|
|
|
2
2
|
|
|
3
3
|
`sipgate-mcp` is an open-source, self-hosted Model Context Protocol server for inspecting and configuring a sipgate account. It exposes the sipgate REST API v2 as focused tools for agents such as Claude Code, Claude Desktop, and Codex.
|
|
4
4
|
|
|
5
|
+
Version 0.2 and later default to user-scoped access: tools are constrained to the
|
|
6
|
+
authenticated sipgate user's resources. Account-wide access is an explicit
|
|
7
|
+
administrator-only mode.
|
|
8
|
+
|
|
5
9
|
The server uses stdio only. It does not start an HTTP server or route credentials
|
|
6
10
|
through a third-party service. It sends authentication only from the local MCP
|
|
7
11
|
process directly to `https://api.sipgate.com/v2`.
|
|
8
12
|
|
|
13
|
+
## Agent-assisted setup
|
|
14
|
+
|
|
15
|
+
Tell Codex or Claude:
|
|
16
|
+
|
|
17
|
+
> Set up sipgate MCP by following
|
|
18
|
+
> https://raw.githubusercontent.com/wiesson/sipgate-mcp/main/SKILL.md
|
|
19
|
+
|
|
20
|
+
The linked, versioned [`SKILL.md`](SKILL.md) tells the agent how to install and
|
|
21
|
+
verify the matching package without asking for credentials in chat. Secret
|
|
22
|
+
entry remains an interactive local Keychain step controlled by the user.
|
|
23
|
+
|
|
9
24
|
## Requirements
|
|
10
25
|
|
|
11
26
|
- Node.js 22 or newer
|
|
12
27
|
- A sipgate account with a Personal Access Token (PAT)
|
|
13
28
|
- An MCP client with stdio support
|
|
14
29
|
|
|
15
|
-
|
|
16
|
-
supported package managers:
|
|
30
|
+
Install the command globally with any of the supported package managers:
|
|
17
31
|
|
|
18
32
|
```bash
|
|
19
33
|
npm install --global sipgate-mcp
|
|
@@ -21,54 +35,114 @@ pnpm add --global sipgate-mcp
|
|
|
21
35
|
vp install --global sipgate-mcp
|
|
22
36
|
```
|
|
23
37
|
|
|
24
|
-
|
|
38
|
+
On macOS, run the interactive setup once:
|
|
25
39
|
|
|
26
40
|
```bash
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
41
|
+
sipgate-mcp setup
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
The setup stores the PAT token ID and token in macOS Keychain without placing
|
|
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.
|
|
47
|
+
Those clients start and stop the stdio server automatically; `sipgate-mcp` does
|
|
48
|
+
not run as a daemon and does not need to be started manually.
|
|
49
|
+
|
|
50
|
+
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.
|
|
54
|
+
|
|
55
|
+
Secure interactive storage currently supports macOS. Environment variables
|
|
56
|
+
remain available for Linux, Windows, containers, CI, and password-manager
|
|
57
|
+
wrappers. To avoid putting literal credentials in shell history, read them
|
|
58
|
+
interactively:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
printf "sipgate PAT token ID: "
|
|
62
|
+
IFS= read -r SIPGATE_TOKEN_ID
|
|
63
|
+
printf "sipgate PAT token: "
|
|
64
|
+
IFS= read -rs SIPGATE_TOKEN
|
|
65
|
+
printf "\n"
|
|
66
|
+
export SIPGATE_TOKEN_ID SIPGATE_TOKEN
|
|
67
|
+
export SIPGATE_MCP_SCOPE="user"
|
|
68
|
+
export SIPGATE_MCP_READONLY="1"
|
|
30
69
|
```
|
|
31
70
|
|
|
32
71
|
For clients that manage MCP commands on demand, `npx -y sipgate-mcp` remains
|
|
33
|
-
supported without a global installation.
|
|
34
|
-
checked on 2026-08-30; this repository is configured for `sipgate-mcp`, but the
|
|
35
|
-
initial npm publish still needs to be completed.
|
|
72
|
+
supported without a global installation.
|
|
36
73
|
|
|
37
74
|
## Create a Personal Access Token
|
|
38
75
|
|
|
39
76
|
1. Open [sipgate Personal Access Tokens](https://app.sipgate.com/personal-access-token).
|
|
40
77
|
2. Select **Add token**, give the token a recognizable name, and select the scopes needed for the tools you intend to use.
|
|
41
78
|
3. Copy both the token ID and token. sipgate displays the token itself only once.
|
|
42
|
-
4.
|
|
79
|
+
4. Run `sipgate-mcp setup` on macOS, or provide them as `SIPGATE_TOKEN_ID` and `SIPGATE_TOKEN` in the MCP process environment.
|
|
43
80
|
|
|
44
81
|
sipgate PAT authentication uses HTTP Basic Auth with `token-id:token` as the credential pair. `sipgate-mcp` constructs that header in memory. See sipgate's [authentication guide](https://en.sipgate.io/rest-api/authentication).
|
|
45
82
|
|
|
46
|
-
Do not put either value in this repository, an MCP config committed to source control, command output, or an issue report.
|
|
83
|
+
Do not put either value in this repository, an MCP config committed to source control, shell command arguments, command output, or an issue report.
|
|
84
|
+
|
|
85
|
+
The separate **API Clients** screen in the sipgate account creates OAuth 2.0
|
|
86
|
+
client credentials for an application that redirects users through sipgate's
|
|
87
|
+
authorization flow. Those client credentials are not PAT replacements and are
|
|
88
|
+
not used by the local stdio setup. They are relevant to a future hosted/remote
|
|
89
|
+
MCP, which would need a registered redirect URI, user consent, access-token
|
|
90
|
+
refresh, and secure per-user token storage. See sipgate's [OAuth authentication
|
|
91
|
+
flow](https://en.sipgate.io/rest-api/authentication#oauth2) and [API client
|
|
92
|
+
management](https://en.sipgate.io/rest-api/managing-third-party-clients).
|
|
93
|
+
|
|
94
|
+
## MCP access scopes
|
|
95
|
+
|
|
96
|
+
`SIPGATE_MCP_SCOPE` controls the resource boundary enforced by the MCP in
|
|
97
|
+
addition to sipgate's own user role and PAT scopes:
|
|
98
|
+
|
|
99
|
+
| Value | Behavior |
|
|
100
|
+
| --- | --- |
|
|
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. |
|
|
102
|
+
| `account` | Enables account-wide reads and writes. Startup fails unless `/users/{authenticatedUserId}` reports `admin: true`. Requires `users:read` for the administrator check. |
|
|
103
|
+
|
|
104
|
+
Token scopes are permission ceilings, not role elevation. For example,
|
|
105
|
+
`numbers:write` does not turn a regular sipgate user into an administrator.
|
|
106
|
+
The effective permission is the intersection of the sipgate user role, PAT
|
|
107
|
+
scopes, MCP access scope, and read-only mode.
|
|
108
|
+
|
|
109
|
+
Use account scope only when account-wide administration is intended:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
export SIPGATE_MCP_SCOPE="account"
|
|
113
|
+
npx -y sipgate-mcp
|
|
114
|
+
```
|
|
47
115
|
|
|
48
116
|
## Tools and PAT scopes
|
|
49
117
|
|
|
50
|
-
|
|
118
|
+
Every mode identifies the authenticated user with `GET /authorization/userinfo`.
|
|
119
|
+
The table lists the non-`all` scopes named by sipgate's live Swagger document,
|
|
120
|
+
including ownership checks performed in user scope and pre/post state reads.
|
|
121
|
+
sipgate also exposes broader parent scopes such as `sessions:write`; select the
|
|
122
|
+
listed specific and parent scopes offered by the PAT UI when in doubt.
|
|
51
123
|
|
|
52
124
|
| Tool | Access | sipgate API calls | PAT scopes |
|
|
53
125
|
| --- | --- | --- | --- |
|
|
54
|
-
| `account_info` | Read |
|
|
55
|
-
| `list_users` | Read | `GET /users` | `users:read` |
|
|
56
|
-
| `list_numbers` | Read | `GET /numbers` | `numbers:read` |
|
|
57
|
-
| `list_devices` | Read | `GET /users`, `GET /{userId}/devices` | `devices:read`; `users:read` when `user_id` is omitted |
|
|
58
|
-
| `get_routing` | Read |
|
|
59
|
-
| `call_history` | Read | `GET /history` | `history:read` |
|
|
126
|
+
| `account_info` | Read | User: cached `/authorization/userinfo`; account: plus `GET /account` | Account: `account:read` (`userinfo` has no scope declaration in Swagger) |
|
|
127
|
+
| `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` |
|
|
129
|
+
| `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 |
|
|
130
|
+
| `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
|
+
| `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` |
|
|
60
132
|
| `get_settings` | Read | `GET /users[/userId]`, `GET /{userId}/devices`, `GET /{userId}/phonelines[/phonelineId]` | `users:read`, `devices:read`, `phonelines:read` |
|
|
61
|
-
| `set_number_routing` | Write | pre/post `GET /numbers
|
|
62
|
-
| `set_forwarding` | Write | pre/post
|
|
63
|
-
| `set_dnd` | Write | pre/post `GET /devices/{deviceId}
|
|
133
|
+
| `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
|
+
| `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
|
+
| `set_dnd` | Write | User: device ownership read; then pre/post `GET /devices/{deviceId}` and `PUT` | `devices:read`, `devices:write` |
|
|
64
136
|
| `send_sms` | Write/action | `GET /{userId}/sms`, pre/post `GET /history`, `POST /sessions/sms` | `sms:read`, `history:read`, `sessions:write`, `sessions:sms:write` |
|
|
65
|
-
| `initiate_call` | Write/action | pre/post `GET /calls
|
|
137
|
+
| `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` |
|
|
66
138
|
|
|
67
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.
|
|
68
140
|
|
|
69
141
|
### Tool notes
|
|
70
142
|
|
|
71
143
|
- `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.
|
|
145
|
+
- User-scoped number-routing snapshots are also resolved through owned phonelines, and user-scoped Click2Dial deliberately omits account-wide `/calls` snapshots.
|
|
72
146
|
- Number routing uses sipgate's documented `endpointId`. Obtain existing IDs from the read tools; a phoneline ID such as `p0` is the documented example.
|
|
73
147
|
- `set_forwarding` replaces the complete phoneline forwarding list. Pass `forwardings: []` to remove all forwardings. A `timeout` of `0` represents immediate forwarding.
|
|
74
148
|
- `send_sms` refuses to post unless `GET /{userId}/sms` returns the requested (or first available) SMS extension.
|
|
@@ -80,12 +154,16 @@ Set `SIPGATE_MCP_READONLY=1` to register only the seven read tools. Write tools
|
|
|
80
154
|
|
|
81
155
|
```bash
|
|
82
156
|
export SIPGATE_MCP_READONLY=1
|
|
157
|
+
export SIPGATE_MCP_SCOPE=user
|
|
83
158
|
npx -y sipgate-mcp
|
|
84
159
|
```
|
|
85
160
|
|
|
86
161
|
## MCP client configuration
|
|
87
162
|
|
|
88
|
-
|
|
163
|
+
The recommended macOS path is `sipgate-mcp setup`. The following manual
|
|
164
|
+
examples are useful for other platforms and custom launchers. Set
|
|
165
|
+
`SIPGATE_TOKEN_ID` and `SIPGATE_TOKEN` in the environment that launches the MCP
|
|
166
|
+
client; the examples keep secret values out of configuration files.
|
|
89
167
|
|
|
90
168
|
### Claude Code
|
|
91
169
|
|
|
@@ -95,12 +173,13 @@ Claude Code expands `${VAR}` references in MCP environment entries. Single quote
|
|
|
95
173
|
claude mcp add \
|
|
96
174
|
--env 'SIPGATE_TOKEN_ID=${SIPGATE_TOKEN_ID}' \
|
|
97
175
|
--env 'SIPGATE_TOKEN=${SIPGATE_TOKEN}' \
|
|
176
|
+
--env SIPGATE_MCP_SCOPE=user \
|
|
98
177
|
--transport stdio \
|
|
99
178
|
--scope user \
|
|
100
179
|
sipgate -- npx -y sipgate-mcp
|
|
101
180
|
```
|
|
102
181
|
|
|
103
|
-
Add `--env SIPGATE_MCP_READONLY=1` before `--transport` for read-only mode. Verify the connection with `claude mcp get sipgate`. See the official [Claude Code MCP documentation](https://code.claude.com/docs/en/mcp).
|
|
182
|
+
Add `--env SIPGATE_MCP_READONLY=1` before `--transport` for read-only mode. Replace the scope with `account` only for deliberate administrator access. Verify the connection with `claude mcp get sipgate`. See the official [Claude Code MCP documentation](https://code.claude.com/docs/en/mcp).
|
|
104
183
|
|
|
105
184
|
### Claude Desktop
|
|
106
185
|
|
|
@@ -127,18 +206,22 @@ Codex can forward named variables from its local environment without storing the
|
|
|
127
206
|
[mcp_servers.sipgate]
|
|
128
207
|
command = "npx"
|
|
129
208
|
args = ["-y", "sipgate-mcp"]
|
|
130
|
-
env_vars = ["SIPGATE_TOKEN_ID", "SIPGATE_TOKEN", "SIPGATE_MCP_READONLY"]
|
|
209
|
+
env_vars = ["SIPGATE_TOKEN_ID", "SIPGATE_TOKEN", "SIPGATE_MCP_SCOPE", "SIPGATE_MCP_READONLY"]
|
|
131
210
|
```
|
|
132
211
|
|
|
133
212
|
Export the variables before starting Codex, then use `/mcp` or `codex mcp list` to confirm the server. The `env_vars` forwarding form is documented in the [official OpenAI MCP documentation](https://developers.openai.com/codex/mcp/).
|
|
134
213
|
|
|
135
214
|
## Manual smoke test with MCP Inspector
|
|
136
215
|
|
|
137
|
-
This test makes real sipgate API calls. Start
|
|
216
|
+
This test makes real sipgate API calls. Start in user/read-only mode with a PAT
|
|
217
|
+
containing `phonelines:read` and `phonelines:numbers:read`, plus the required
|
|
218
|
+
environment variables:
|
|
138
219
|
|
|
139
220
|
```bash
|
|
140
221
|
export SIPGATE_TOKEN_ID="your-token-id"
|
|
141
222
|
export SIPGATE_TOKEN="your-token"
|
|
223
|
+
export SIPGATE_MCP_SCOPE="user"
|
|
224
|
+
export SIPGATE_MCP_READONLY=1
|
|
142
225
|
npx @modelcontextprotocol/inspector npx -y sipgate-mcp
|
|
143
226
|
```
|
|
144
227
|
|
|
@@ -158,17 +241,24 @@ The MCP layer depends only on the backend interface:
|
|
|
158
241
|
```text
|
|
159
242
|
MCP stdio server
|
|
160
243
|
-> validated tool definitions (Zod)
|
|
161
|
-
->
|
|
162
|
-
->
|
|
163
|
-
->
|
|
164
|
-
->
|
|
244
|
+
-> user/account access policy
|
|
245
|
+
-> TelephonyBackend
|
|
246
|
+
-> SipgateBackend
|
|
247
|
+
-> SipgateClient
|
|
248
|
+
-> native fetch -> https://api.sipgate.com/v2
|
|
165
249
|
```
|
|
166
250
|
|
|
167
251
|
`TelephonyBackend` contains the stable, provider-neutral operations. `SipgateBackend` is the only v1 implementation, so a future second telephony provider can reuse the same MCP tool surface.
|
|
168
252
|
|
|
169
253
|
## Security
|
|
170
254
|
|
|
171
|
-
- PAT values are read
|
|
255
|
+
- PAT values are read from `SIPGATE_TOKEN_ID` and `SIPGATE_TOKEN`, or from the
|
|
256
|
+
current user's macOS Keychain when both variables are absent.
|
|
257
|
+
- `sipgate-mcp setup` delegates secret entry directly to the macOS Keychain
|
|
258
|
+
prompt. Secret values are never passed as command-line arguments and are not
|
|
259
|
+
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.
|
|
261
|
+
- Account scope fails startup unless the authenticated sipgate user reports `admin: true`.
|
|
172
262
|
- The Basic Auth header exists only in memory and is sent only to the fixed sipgate API base URL.
|
|
173
263
|
- API error bodies are discarded. User-facing errors never include request headers, response bodies, or credentials.
|
|
174
264
|
- Potentially sensitive response properties such as `credentials`, `password`, `token`, and `secret` are redacted before tool output.
|
|
@@ -184,7 +274,7 @@ npm run build
|
|
|
184
274
|
npm test
|
|
185
275
|
```
|
|
186
276
|
|
|
187
|
-
Tests use `node:test` and mocked `fetch`; they never call the real sipgate API. The suite includes client authentication/error behavior, exact critical write payloads, credential redaction, one test per MCP tool, and read-only registration.
|
|
277
|
+
Tests use `node:test` and mocked `fetch`; they never call the real sipgate API. The suite includes client authentication/error behavior, user/account access-policy enforcement, exact critical write payloads, credential redaction, one test per MCP tool, and read-only registration.
|
|
188
278
|
|
|
189
279
|
## Releases
|
|
190
280
|
|
|
@@ -203,8 +293,9 @@ The endpoint paths, query parameters, request bodies, response models, and scope
|
|
|
203
293
|
|
|
204
294
|
## Roadmap
|
|
205
295
|
|
|
206
|
-
-
|
|
207
|
-
-
|
|
296
|
+
- v0.1: local self-hosted stdio server and sipgate REST API tools
|
|
297
|
+
- v0.2: user-scoped access by default plus explicit administrator-only account scope
|
|
298
|
+
- Future: optional remote deployment, including a Cloudflare Workers backend, without changing the MCP tool surface
|
|
208
299
|
- Additional `TelephonyBackend` implementation(s)
|
|
209
300
|
- Product-aware Click2Dial behavior for classic and Neo PBX accounts
|
|
210
301
|
|
package/SKILL.md
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sipgate-mcp
|
|
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
|
+
metadata:
|
|
5
|
+
version: "0.3.0"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Set up sipgate MCP
|
|
9
|
+
|
|
10
|
+
Install the matching CLI version with one available package manager:
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
vp install -g sipgate-mcp@0.3.0
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install -g sipgate-mcp@0.3.0
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pnpm add -g sipgate-mcp@0.3.0
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Run only one install command. Confirm that `sipgate-mcp --version` reports
|
|
25
|
+
`0.3.0` before continuing.
|
|
26
|
+
|
|
27
|
+
## Security boundary
|
|
28
|
+
|
|
29
|
+
- Never ask the user to paste a sipgate PAT, token, client secret, or other
|
|
30
|
+
credential into chat.
|
|
31
|
+
- Never place credentials in command arguments, MCP configuration, repository
|
|
32
|
+
files, logs, or issue reports.
|
|
33
|
+
- The local server uses a sipgate Personal Access Token. A sipgate OAuth API
|
|
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
|
|
36
|
+
account-wide administrator access without an explicit user request.
|
|
37
|
+
- Do not remove or replace an existing MCP configuration without the user's
|
|
38
|
+
approval.
|
|
39
|
+
|
|
40
|
+
## Configure
|
|
41
|
+
|
|
42
|
+
On macOS, run the interactive setup for the MCP client the user is currently
|
|
43
|
+
using:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
sipgate-mcp setup --client codex
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
or:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
sipgate-mcp setup --client claude
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Omit `--client` only when both installed clients should be configured. The
|
|
56
|
+
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.
|
|
59
|
+
|
|
60
|
+
If the Keychain prompt cannot be presented in the current environment, ask the
|
|
61
|
+
user to run the setup command in their local interactive terminal. Do not ask
|
|
62
|
+
them to provide the credential to the agent instead. On Linux or Windows,
|
|
63
|
+
follow the secret-free environment or password-manager launcher guidance in
|
|
64
|
+
the project README rather than inventing a plaintext credential file.
|
|
65
|
+
|
|
66
|
+
If setup reports that an MCP server named `sipgate` already exists, inspect it
|
|
67
|
+
with `codex mcp get sipgate` or `claude mcp get sipgate`. Explain the conflict
|
|
68
|
+
and request approval before removing or replacing that configuration.
|
|
69
|
+
|
|
70
|
+
## Verify
|
|
71
|
+
|
|
72
|
+
Use the applicable client command:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
codex mcp get sipgate
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
claude mcp get sipgate
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Ask the user to restart the client when required, open `/mcp`, and test with:
|
|
83
|
+
|
|
84
|
+
> Use sipgate read-only. Check the connection and list my phone numbers.
|
|
85
|
+
|
|
86
|
+
Do not enable `--allow-writes` merely to make a failed read test pass. Diagnose
|
|
87
|
+
installation, credentials, client registration, and PAT read scopes first.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { AccessScope, AuthenticatedUserContext, DeviceType, ForwardingRule, HistoryQuery, JsonValue, MutationResult, PaginationInput, TelephonyBackend } from "./telephony-backend.js";
|
|
2
|
+
export declare class AccessPolicyError extends Error {
|
|
3
|
+
constructor(message: string);
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Enforces MCP-level resource boundaries in addition to sipgate's own role and
|
|
7
|
+
* token-scope checks. Account scope is rejected unless sipgate identifies the
|
|
8
|
+
* authenticated user as an administrator.
|
|
9
|
+
*/
|
|
10
|
+
export declare class AccessControlledBackend implements TelephonyBackend {
|
|
11
|
+
private readonly delegate;
|
|
12
|
+
private readonly scope;
|
|
13
|
+
private readonly context;
|
|
14
|
+
constructor(delegate: TelephonyBackend, scope: AccessScope, context: AuthenticatedUserContext);
|
|
15
|
+
getAuthenticatedUser(): Promise<AuthenticatedUserContext>;
|
|
16
|
+
getUser(userId: string): Promise<JsonValue>;
|
|
17
|
+
getAccountInfo(): Promise<JsonValue>;
|
|
18
|
+
listUsers(): Promise<JsonValue>;
|
|
19
|
+
listNumbers({ offset, limit }: PaginationInput): Promise<JsonValue>;
|
|
20
|
+
listUserNumbers(userId: string, pagination: PaginationInput): Promise<JsonValue>;
|
|
21
|
+
listPhonelines(userId: string): Promise<JsonValue>;
|
|
22
|
+
listDevices(userId?: string, types?: DeviceType[]): Promise<JsonValue>;
|
|
23
|
+
getRouting(userId?: string): Promise<JsonValue>;
|
|
24
|
+
getCallHistory(query: HistoryQuery): Promise<JsonValue>;
|
|
25
|
+
getSettings(userId?: string): Promise<JsonValue>;
|
|
26
|
+
setNumberRouting(numberId: string, endpointId: string): Promise<MutationResult>;
|
|
27
|
+
setUserNumberRouting(userId: string, numberId: string, endpointId: string): Promise<MutationResult>;
|
|
28
|
+
setForwarding(userId: string, phonelineId: string, forwardings: ForwardingRule[]): Promise<MutationResult>;
|
|
29
|
+
setDnd(deviceId: string, enabled: boolean): Promise<MutationResult>;
|
|
30
|
+
sendSms(input: {
|
|
31
|
+
userId: string;
|
|
32
|
+
smsId?: string;
|
|
33
|
+
recipient: string;
|
|
34
|
+
message: string;
|
|
35
|
+
sendAt?: number;
|
|
36
|
+
}): Promise<MutationResult>;
|
|
37
|
+
initiateCall(input: {
|
|
38
|
+
caller: string;
|
|
39
|
+
callee: string;
|
|
40
|
+
callerId?: string;
|
|
41
|
+
deviceId?: string;
|
|
42
|
+
}): Promise<MutationResult>;
|
|
43
|
+
initiateUserCall(input: {
|
|
44
|
+
caller: string;
|
|
45
|
+
callee: string;
|
|
46
|
+
callerId?: string;
|
|
47
|
+
deviceId?: string;
|
|
48
|
+
}): Promise<MutationResult>;
|
|
49
|
+
private assertUser;
|
|
50
|
+
private assertOwned;
|
|
51
|
+
private ownedConnectionIds;
|
|
52
|
+
private ownedPhonelineIds;
|
|
53
|
+
private ownedDeviceIds;
|
|
54
|
+
private ownedNumbers;
|
|
55
|
+
}
|
|
56
|
+
export declare function createAccessControlledBackend(delegate: TelephonyBackend, scope: AccessScope): Promise<AccessControlledBackend>;
|
|
57
|
+
//# sourceMappingURL=access-controlled-backend.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"access-controlled-backend.d.ts","sourceRoot":"","sources":["../../src/backend/access-controlled-backend.ts"],"names":[],"mappings":"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"}
|