sipgate-mcp 0.2.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 +12 -0
- package/README.md +60 -9
- package/SKILL.md +87 -0
- package/dist/config.d.ts +2 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +9 -4
- 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 +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +33 -3
- package/dist/index.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/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 +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
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
|
+
|
|
3
15
|
## 0.2.0 - 2026-08-30
|
|
4
16
|
|
|
5
17
|
- Default to MCP-level user scope resolved from sipgate's authenticated user.
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
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
|
|
5
|
+
Version 0.2 and later default to user-scoped access: tools are constrained to the
|
|
6
6
|
authenticated sipgate user's resources. Account-wide access is an explicit
|
|
7
7
|
administrator-only mode.
|
|
8
8
|
|
|
@@ -10,6 +10,17 @@ The server uses stdio only. It does not start an HTTP server or route credential
|
|
|
10
10
|
through a third-party service. It sends authentication only from the local MCP
|
|
11
11
|
process directly to `https://api.sipgate.com/v2`.
|
|
12
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
|
+
|
|
13
24
|
## Requirements
|
|
14
25
|
|
|
15
26
|
- Node.js 22 or newer
|
|
@@ -24,13 +35,37 @@ pnpm add --global sipgate-mcp
|
|
|
24
35
|
vp install --global sipgate-mcp
|
|
25
36
|
```
|
|
26
37
|
|
|
27
|
-
|
|
38
|
+
On macOS, run the interactive setup once:
|
|
28
39
|
|
|
29
40
|
```bash
|
|
30
|
-
|
|
31
|
-
|
|
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
|
|
32
67
|
export SIPGATE_MCP_SCOPE="user"
|
|
33
|
-
|
|
68
|
+
export SIPGATE_MCP_READONLY="1"
|
|
34
69
|
```
|
|
35
70
|
|
|
36
71
|
For clients that manage MCP commands on demand, `npx -y sipgate-mcp` remains
|
|
@@ -41,11 +76,20 @@ supported without a global installation.
|
|
|
41
76
|
1. Open [sipgate Personal Access Tokens](https://app.sipgate.com/personal-access-token).
|
|
42
77
|
2. Select **Add token**, give the token a recognizable name, and select the scopes needed for the tools you intend to use.
|
|
43
78
|
3. Copy both the token ID and token. sipgate displays the token itself only once.
|
|
44
|
-
4.
|
|
79
|
+
4. Run `sipgate-mcp setup` on macOS, or provide them as `SIPGATE_TOKEN_ID` and `SIPGATE_TOKEN` in the MCP process environment.
|
|
45
80
|
|
|
46
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).
|
|
47
82
|
|
|
48
|
-
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).
|
|
49
93
|
|
|
50
94
|
## MCP access scopes
|
|
51
95
|
|
|
@@ -116,7 +160,10 @@ npx -y sipgate-mcp
|
|
|
116
160
|
|
|
117
161
|
## MCP client configuration
|
|
118
162
|
|
|
119
|
-
|
|
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.
|
|
120
167
|
|
|
121
168
|
### Claude Code
|
|
122
169
|
|
|
@@ -205,7 +252,11 @@ MCP stdio server
|
|
|
205
252
|
|
|
206
253
|
## Security
|
|
207
254
|
|
|
208
|
-
- 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.
|
|
209
260
|
- User scope is the default and validates user IDs plus number, phoneline, device, call, and history ownership before delegation.
|
|
210
261
|
- Account scope fails startup unless the authenticated sipgate user reports `admin: true`.
|
|
211
262
|
- The Basic Auth header exists only in memory and is sent only to the fixed sipgate API base URL.
|
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.
|
package/dist/config.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type { AccessScope } from "./backend/telephony-backend.js";
|
|
2
|
+
import { type SipgateCredentials } from "./credentials.js";
|
|
2
3
|
export interface ServerConfig {
|
|
3
4
|
accessScope: AccessScope;
|
|
4
5
|
tokenId: string;
|
|
5
6
|
token: string;
|
|
6
7
|
readonly: boolean;
|
|
7
8
|
}
|
|
8
|
-
export declare function loadConfig(env?: NodeJS.ProcessEnv): ServerConfig;
|
|
9
|
+
export declare function loadConfig(env?: NodeJS.ProcessEnv, storedCredentialLoader?: () => SipgateCredentials | undefined): ServerConfig;
|
|
9
10
|
//# sourceMappingURL=config.d.ts.map
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,EAEL,KAAK,kBAAkB,EACxB,MAAM,kBAAkB,CAAC;AAE1B,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,WAAW,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,wBAAgB,UAAU,CACxB,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,sBAAsB,GAAE,MAAM,kBAAkB,GAAG,SAAiC,GACnF,YAAY,CAwBd"}
|
package/dist/config.js
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const
|
|
1
|
+
import { loadStoredCredentials, } from "./credentials.js";
|
|
2
|
+
export function loadConfig(env = process.env, storedCredentialLoader = loadStoredCredentials) {
|
|
3
|
+
const hasEnvironmentCredential = Boolean(env.SIPGATE_TOKEN_ID || env.SIPGATE_TOKEN);
|
|
4
|
+
const storedCredentials = hasEnvironmentCredential
|
|
5
|
+
? undefined
|
|
6
|
+
: storedCredentialLoader();
|
|
7
|
+
const tokenId = env.SIPGATE_TOKEN_ID ?? storedCredentials?.tokenId;
|
|
8
|
+
const token = env.SIPGATE_TOKEN ?? storedCredentials?.token;
|
|
4
9
|
if (!tokenId || !token) {
|
|
5
|
-
throw new Error("
|
|
10
|
+
throw new Error("Credentials are missing. Run 'sipgate-mcp setup' or set both SIPGATE_TOKEN_ID and SIPGATE_TOKEN.");
|
|
6
11
|
}
|
|
7
12
|
const accessScope = env.SIPGATE_MCP_SCOPE ?? "user";
|
|
8
13
|
if (accessScope !== "user" && accessScope !== "account") {
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AACA,OAAO,EACL,qBAAqB,GAEtB,MAAM,kBAAkB,CAAC;AAS1B,MAAM,UAAU,UAAU,CACxB,GAAG,GAAsB,OAAO,CAAC,GAAG,EACpC,sBAAsB,GAAyC,qBAAqB;IAEpF,MAAM,wBAAwB,GAAG,OAAO,CACtC,GAAG,CAAC,gBAAgB,IAAI,GAAG,CAAC,aAAa,CAC1C,CAAC;IACF,MAAM,iBAAiB,GAAG,wBAAwB;QAChD,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,sBAAsB,EAAE,CAAC;IAC7B,MAAM,OAAO,GAAG,GAAG,CAAC,gBAAgB,IAAI,iBAAiB,EAAE,OAAO,CAAC;IACnE,MAAM,KAAK,GAAG,GAAG,CAAC,aAAa,IAAI,iBAAiB,EAAE,KAAK,CAAC;IAC5D,IAAI,CAAC,OAAO,IAAI,CAAC,KAAK,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CACb,kGAAkG,CACnG,CAAC;IACJ,CAAC;IACD,MAAM,WAAW,GAAG,GAAG,CAAC,iBAAiB,IAAI,MAAM,CAAC;IACpD,IAAI,WAAW,KAAK,MAAM,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;QACxD,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;IAC3E,CAAC;IACD,OAAO;QACL,WAAW;QACX,OAAO;QACP,KAAK;QACL,QAAQ,EAAE,GAAG,CAAC,oBAAoB,KAAK,GAAG;KAC3C,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface SipgateCredentials {
|
|
2
|
+
tokenId: string;
|
|
3
|
+
token: string;
|
|
4
|
+
}
|
|
5
|
+
export declare const MACOS_KEYCHAIN_SERVICE = "sipgate-mcp";
|
|
6
|
+
export declare const MACOS_KEYCHAIN_TOKEN_ID_ACCOUNT = "pat-token-id";
|
|
7
|
+
export declare const MACOS_KEYCHAIN_TOKEN_ACCOUNT = "pat-token";
|
|
8
|
+
type KeychainReader = (account: string) => string;
|
|
9
|
+
type KeychainWriter = (account: string) => void;
|
|
10
|
+
export declare function loadStoredCredentials(platform?: NodeJS.Platform, readKeychain?: KeychainReader): SipgateCredentials | undefined;
|
|
11
|
+
export declare function storeCredentialsInteractively(platform?: NodeJS.Platform, writeKeychain?: KeychainWriter, output?: Pick<NodeJS.WriteStream, "write">): void;
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=credentials.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../src/credentials.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,eAAO,MAAM,sBAAsB,gBAAgB,CAAC;AACpD,eAAO,MAAM,+BAA+B,iBAAiB,CAAC;AAC9D,eAAO,MAAM,4BAA4B,cAAc,CAAC;AAExD,KAAK,cAAc,GAAG,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC;AAClD,KAAK,cAAc,GAAG,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;AAwChD,wBAAgB,qBAAqB,CACnC,QAAQ,GAAE,MAAM,CAAC,QAA2B,EAC5C,YAAY,GAAE,cAAsC,GACnD,kBAAkB,GAAG,SAAS,CAehC;AAED,wBAAgB,6BAA6B,CAC3C,QAAQ,GAAE,MAAM,CAAC,QAA2B,EAC5C,aAAa,GAAE,cAAsC,EACrD,MAAM,GAAE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAkB,GACzD,IAAI,CAWN"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { execFileSync, spawnSync } from "node:child_process";
|
|
2
|
+
export const MACOS_KEYCHAIN_SERVICE = "sipgate-mcp";
|
|
3
|
+
export const MACOS_KEYCHAIN_TOKEN_ID_ACCOUNT = "pat-token-id";
|
|
4
|
+
export const MACOS_KEYCHAIN_TOKEN_ACCOUNT = "pat-token";
|
|
5
|
+
function defaultKeychainReader(account) {
|
|
6
|
+
return execFileSync("/usr/bin/security", [
|
|
7
|
+
"find-generic-password",
|
|
8
|
+
"-s",
|
|
9
|
+
MACOS_KEYCHAIN_SERVICE,
|
|
10
|
+
"-a",
|
|
11
|
+
account,
|
|
12
|
+
"-w",
|
|
13
|
+
], {
|
|
14
|
+
encoding: "utf8",
|
|
15
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
16
|
+
}).trim();
|
|
17
|
+
}
|
|
18
|
+
function defaultKeychainWriter(account) {
|
|
19
|
+
const result = spawnSync("/usr/bin/security", [
|
|
20
|
+
"add-generic-password",
|
|
21
|
+
"-a",
|
|
22
|
+
account,
|
|
23
|
+
"-s",
|
|
24
|
+
MACOS_KEYCHAIN_SERVICE,
|
|
25
|
+
"-U",
|
|
26
|
+
"-w",
|
|
27
|
+
], { stdio: "inherit" });
|
|
28
|
+
if (result.error || result.status !== 0) {
|
|
29
|
+
throw new Error("macOS Keychain did not store the credential.");
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export function loadStoredCredentials(platform = process.platform, readKeychain = defaultKeychainReader) {
|
|
33
|
+
if (platform !== "darwin") {
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
try {
|
|
37
|
+
const tokenId = readKeychain(MACOS_KEYCHAIN_TOKEN_ID_ACCOUNT).trim();
|
|
38
|
+
const token = readKeychain(MACOS_KEYCHAIN_TOKEN_ACCOUNT).trim();
|
|
39
|
+
if (!tokenId || !token) {
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
return { tokenId, token };
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
export function storeCredentialsInteractively(platform = process.platform, writeKeychain = defaultKeychainWriter, output = process.stderr) {
|
|
49
|
+
if (platform !== "darwin") {
|
|
50
|
+
throw new Error("Secure interactive setup currently supports macOS Keychain only. Use SIPGATE_TOKEN_ID and SIPGATE_TOKEN on this platform.");
|
|
51
|
+
}
|
|
52
|
+
output.write("Enter the sipgate PAT token ID in the macOS Keychain prompt.\n");
|
|
53
|
+
writeKeychain(MACOS_KEYCHAIN_TOKEN_ID_ACCOUNT);
|
|
54
|
+
output.write("Enter the sipgate PAT token in the macOS Keychain prompt.\n");
|
|
55
|
+
writeKeychain(MACOS_KEYCHAIN_TOKEN_ACCOUNT);
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=credentials.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credentials.js","sourceRoot":"","sources":["../src/credentials.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAO7D,MAAM,CAAC,MAAM,sBAAsB,GAAG,aAAa,CAAC;AACpD,MAAM,CAAC,MAAM,+BAA+B,GAAG,cAAc,CAAC;AAC9D,MAAM,CAAC,MAAM,4BAA4B,GAAG,WAAW,CAAC;AAKxD,SAAS,qBAAqB,CAAC,OAAe;IAC5C,OAAO,YAAY,CACjB,mBAAmB,EACnB;QACE,uBAAuB;QACvB,IAAI;QACJ,sBAAsB;QACtB,IAAI;QACJ,OAAO;QACP,IAAI;KACL,EACD;QACE,QAAQ,EAAE,MAAM;QAChB,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC;KACpC,CACF,CAAC,IAAI,EAAE,CAAC;AACX,CAAC;AAED,SAAS,qBAAqB,CAAC,OAAe;IAC5C,MAAM,MAAM,GAAG,SAAS,CACtB,mBAAmB,EACnB;QACE,sBAAsB;QACtB,IAAI;QACJ,OAAO;QACP,IAAI;QACJ,sBAAsB;QACtB,IAAI;QACJ,IAAI;KACL,EACD,EAAE,KAAK,EAAE,SAAS,EAAE,CACrB,CAAC;IAEF,IAAI,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxC,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;IAClE,CAAC;AACH,CAAC;AAED,MAAM,UAAU,qBAAqB,CACnC,QAAQ,GAAoB,OAAO,CAAC,QAAQ,EAC5C,YAAY,GAAmB,qBAAqB;IAEpD,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC1B,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,YAAY,CAAC,+BAA+B,CAAC,CAAC,IAAI,EAAE,CAAC;QACrE,MAAM,KAAK,GAAG,YAAY,CAAC,4BAA4B,CAAC,CAAC,IAAI,EAAE,CAAC;QAChE,IAAI,CAAC,OAAO,IAAI,CAAC,KAAK,EAAE,CAAC;YACvB,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,6BAA6B,CAC3C,QAAQ,GAAoB,OAAO,CAAC,QAAQ,EAC5C,aAAa,GAAmB,qBAAqB,EACrD,MAAM,GAAsC,OAAO,CAAC,MAAM;IAE1D,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CACb,2HAA2H,CAC5H,CAAC;IACJ,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,gEAAgE,CAAC,CAAC;IAC/E,aAAa,CAAC,+BAA+B,CAAC,CAAC;IAC/C,MAAM,CAAC,KAAK,CAAC,6DAA6D,CAAC,CAAC;IAC5E,aAAa,CAAC,4BAA4B,CAAC,CAAC;AAC9C,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
export declare function main(): Promise<void>;
|
|
3
|
+
export declare function runCli(args?: string[]): Promise<void>;
|
|
3
4
|
export declare function isMainModule(moduleUrl: string, entrypoint: string | undefined): boolean;
|
|
4
5
|
export { SipgateBackend } from "./backend/sipgate-backend.js";
|
|
5
6
|
export { AccessPolicyError, createAccessControlledBackend, } from "./backend/access-controlled-backend.js";
|
|
6
7
|
export { SipgateApiError, SipgateClient } from "./backend/sipgate-client.js";
|
|
7
8
|
export type { AccessScope, AuthenticatedUserContext, TelephonyBackend, } from "./backend/telephony-backend.js";
|
|
8
9
|
export { createServer } from "./server.js";
|
|
10
|
+
export { loadStoredCredentials, storeCredentialsInteractively, } from "./credentials.js";
|
|
11
|
+
export { buildRegistrationCommand, parseSetupArgs, runSetup } from "./setup.js";
|
|
9
12
|
export { createToolDefinitions } from "./tools/definitions.js";
|
|
13
|
+
export { VERSION } from "./version.js";
|
|
10
14
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAeA,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAO1C;AAED,wBAAsB,MAAM,CAAC,IAAI,GAAE,MAAM,EAA0B,GAAG,OAAO,CAAC,IAAI,CAAC,CAsBlF;AAED,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAUvF;AAaD,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EACL,iBAAiB,EACjB,6BAA6B,GAC9B,MAAM,wCAAwC,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC7E,YAAY,EACV,WAAW,EACX,wBAAwB,EACxB,gBAAgB,GACjB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EACL,qBAAqB,EACrB,6BAA6B,GAC9B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,wBAAwB,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAChF,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -7,6 +7,8 @@ import { SipgateBackend } from "./backend/sipgate-backend.js";
|
|
|
7
7
|
import { SipgateClient } from "./backend/sipgate-client.js";
|
|
8
8
|
import { loadConfig } from "./config.js";
|
|
9
9
|
import { createServer } from "./server.js";
|
|
10
|
+
import { runSetup, SETUP_HELP, SetupError } from "./setup.js";
|
|
11
|
+
import { VERSION } from "./version.js";
|
|
10
12
|
export async function main() {
|
|
11
13
|
const config = loadConfig();
|
|
12
14
|
const client = new SipgateClient({ tokenId: config.tokenId, token: config.token });
|
|
@@ -15,6 +17,29 @@ export async function main() {
|
|
|
15
17
|
const server = createServer(backend, config.readonly, config.accessScope);
|
|
16
18
|
await server.connect(new StdioServerTransport());
|
|
17
19
|
}
|
|
20
|
+
export async function runCli(args = process.argv.slice(2)) {
|
|
21
|
+
const command = args[0];
|
|
22
|
+
if (command === "setup") {
|
|
23
|
+
if (args[1] === "--help" || args[1] === "-h") {
|
|
24
|
+
process.stdout.write(SETUP_HELP);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
runSetup(args.slice(1));
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
if (command === "--help" || command === "-h" || command === "help") {
|
|
31
|
+
process.stdout.write(SETUP_HELP);
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
if (command === "--version" || command === "-V" || command === "version") {
|
|
35
|
+
process.stdout.write(`${VERSION}\n`);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (command) {
|
|
39
|
+
throw new SetupError(`Unknown command: ${command}`);
|
|
40
|
+
}
|
|
41
|
+
await main();
|
|
42
|
+
}
|
|
18
43
|
export function isMainModule(moduleUrl, entrypoint) {
|
|
19
44
|
if (!entrypoint) {
|
|
20
45
|
return false;
|
|
@@ -27,9 +52,11 @@ export function isMainModule(moduleUrl, entrypoint) {
|
|
|
27
52
|
}
|
|
28
53
|
}
|
|
29
54
|
if (isMainModule(import.meta.url, process.argv[1])) {
|
|
30
|
-
|
|
31
|
-
const detail = error instanceof AccessPolicyError
|
|
32
|
-
|
|
55
|
+
runCli().catch((error) => {
|
|
56
|
+
const detail = error instanceof AccessPolicyError || error instanceof SetupError
|
|
57
|
+
? ` ${error.message}`
|
|
58
|
+
: "";
|
|
59
|
+
console.error(`sipgate-mcp failed.${detail} Check credentials and MCP client configuration.`);
|
|
33
60
|
process.exitCode = 1;
|
|
34
61
|
});
|
|
35
62
|
}
|
|
@@ -37,5 +64,8 @@ export { SipgateBackend } from "./backend/sipgate-backend.js";
|
|
|
37
64
|
export { AccessPolicyError, createAccessControlledBackend, } from "./backend/access-controlled-backend.js";
|
|
38
65
|
export { SipgateApiError, SipgateClient } from "./backend/sipgate-client.js";
|
|
39
66
|
export { createServer } from "./server.js";
|
|
67
|
+
export { loadStoredCredentials, storeCredentialsInteractively, } from "./credentials.js";
|
|
68
|
+
export { buildRegistrationCommand, parseSetupArgs, runSetup } from "./setup.js";
|
|
40
69
|
export { createToolDefinitions } from "./tools/definitions.js";
|
|
70
|
+
export { VERSION } from "./version.js";
|
|
41
71
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EACL,iBAAiB,EACjB,6BAA6B,GAC9B,MAAM,wCAAwC,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/setup.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export type SetupClient = "codex" | "claude";
|
|
2
|
+
export interface SetupOptions {
|
|
3
|
+
allowWrites: boolean;
|
|
4
|
+
clients: SetupClient[];
|
|
5
|
+
dryRun: boolean;
|
|
6
|
+
}
|
|
7
|
+
export interface ClientCommand {
|
|
8
|
+
command: string;
|
|
9
|
+
args: string[];
|
|
10
|
+
}
|
|
11
|
+
export declare class SetupError extends Error {
|
|
12
|
+
}
|
|
13
|
+
export declare function parseSetupArgs(args: string[]): SetupOptions;
|
|
14
|
+
export declare function buildRegistrationCommand(client: SetupClient, nodeExecutable: string, entrypoint: string, allowWrites: boolean): ClientCommand;
|
|
15
|
+
export declare function runSetup(args: string[], entrypointArgument?: string | undefined): void;
|
|
16
|
+
export declare const SETUP_HELP = "Usage:\n sipgate-mcp Start the MCP stdio server\n sipgate-mcp setup [options] Store credentials and register MCP clients\n sipgate-mcp --version Print the installed version\n\nSetup options:\n --client codex|claude Register only this client (repeatable)\n --allow-writes Register write tools; default is read-only\n --dry-run Print registration commands without changing anything\n";
|
|
17
|
+
//# sourceMappingURL=setup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE7C,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,OAAO,CAAC;IACrB,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,qBAAa,UAAW,SAAQ,KAAK;CAAG;AAExC,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,YAAY,CAkC3D;AAED,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,WAAW,EACnB,cAAc,EAAE,MAAM,EACtB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,OAAO,GACnB,aAAa,CA2Cf;AAoBD,wBAAgB,QAAQ,CACtB,IAAI,EAAE,MAAM,EAAE,EACd,kBAAkB,GAAE,MAAM,GAAG,SAA2B,GACvD,IAAI,CA+DN;AAED,eAAO,MAAM,UAAU,qdAStB,CAAC"}
|
package/dist/setup.js
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import { storeCredentialsInteractively } from "./credentials.js";
|
|
4
|
+
export class SetupError extends Error {
|
|
5
|
+
}
|
|
6
|
+
export function parseSetupArgs(args) {
|
|
7
|
+
const clients = [];
|
|
8
|
+
let allowWrites = false;
|
|
9
|
+
let dryRun = false;
|
|
10
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
11
|
+
const argument = args[index];
|
|
12
|
+
if (argument === "--allow-writes") {
|
|
13
|
+
allowWrites = true;
|
|
14
|
+
continue;
|
|
15
|
+
}
|
|
16
|
+
if (argument === "--dry-run") {
|
|
17
|
+
dryRun = true;
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
if (argument === "--client") {
|
|
21
|
+
const client = args[index + 1];
|
|
22
|
+
if (client !== "codex" && client !== "claude") {
|
|
23
|
+
throw new SetupError("--client must be either 'codex' or 'claude'.");
|
|
24
|
+
}
|
|
25
|
+
if (!clients.includes(client)) {
|
|
26
|
+
clients.push(client);
|
|
27
|
+
}
|
|
28
|
+
index += 1;
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
throw new SetupError(`Unknown setup option: ${argument ?? ""}`);
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
allowWrites,
|
|
35
|
+
clients: clients.length > 0 ? clients : ["codex", "claude"],
|
|
36
|
+
dryRun,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
export function buildRegistrationCommand(client, nodeExecutable, entrypoint, allowWrites) {
|
|
40
|
+
const modeEnvironment = [
|
|
41
|
+
"SIPGATE_MCP_SCOPE=user",
|
|
42
|
+
`SIPGATE_MCP_READONLY=${allowWrites ? "0" : "1"}`,
|
|
43
|
+
];
|
|
44
|
+
if (client === "codex") {
|
|
45
|
+
return {
|
|
46
|
+
command: "codex",
|
|
47
|
+
args: [
|
|
48
|
+
"mcp",
|
|
49
|
+
"add",
|
|
50
|
+
"sipgate",
|
|
51
|
+
"--env",
|
|
52
|
+
modeEnvironment[0],
|
|
53
|
+
"--env",
|
|
54
|
+
modeEnvironment[1],
|
|
55
|
+
"--",
|
|
56
|
+
nodeExecutable,
|
|
57
|
+
entrypoint,
|
|
58
|
+
],
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
command: "claude",
|
|
63
|
+
args: [
|
|
64
|
+
"mcp",
|
|
65
|
+
"add",
|
|
66
|
+
"--transport",
|
|
67
|
+
"stdio",
|
|
68
|
+
"--scope",
|
|
69
|
+
"user",
|
|
70
|
+
"--env",
|
|
71
|
+
modeEnvironment[0],
|
|
72
|
+
"--env",
|
|
73
|
+
modeEnvironment[1],
|
|
74
|
+
"sipgate",
|
|
75
|
+
"--",
|
|
76
|
+
nodeExecutable,
|
|
77
|
+
entrypoint,
|
|
78
|
+
],
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
function isCommandAvailable(command) {
|
|
82
|
+
const result = spawnSync(command, ["--version"], { stdio: "ignore" });
|
|
83
|
+
return !result.error && result.status === 0;
|
|
84
|
+
}
|
|
85
|
+
function isAlreadyConfigured(client) {
|
|
86
|
+
const result = spawnSync(client, ["mcp", "get", "sipgate"], {
|
|
87
|
+
stdio: "ignore",
|
|
88
|
+
});
|
|
89
|
+
return !result.error && result.status === 0;
|
|
90
|
+
}
|
|
91
|
+
function shellDisplay(command) {
|
|
92
|
+
return [command.command, ...command.args]
|
|
93
|
+
.map((part) => (/^[A-Za-z0-9_./:=+-]+$/.test(part) ? part : JSON.stringify(part)))
|
|
94
|
+
.join(" ");
|
|
95
|
+
}
|
|
96
|
+
export function runSetup(args, entrypointArgument = process.argv[1]) {
|
|
97
|
+
const options = parseSetupArgs(args);
|
|
98
|
+
if (!entrypointArgument) {
|
|
99
|
+
throw new SetupError("Could not determine the sipgate-mcp entrypoint.");
|
|
100
|
+
}
|
|
101
|
+
const entrypoint = resolve(entrypointArgument);
|
|
102
|
+
const commands = options.clients.map((client) => ({
|
|
103
|
+
client,
|
|
104
|
+
registration: buildRegistrationCommand(client, process.execPath, entrypoint, options.allowWrites),
|
|
105
|
+
}));
|
|
106
|
+
if (options.dryRun) {
|
|
107
|
+
process.stdout.write("Dry run: no credentials or MCP configurations were changed.\n");
|
|
108
|
+
for (const { registration } of commands) {
|
|
109
|
+
process.stdout.write(`${shellDisplay(registration)}\n`);
|
|
110
|
+
}
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
process.stderr.write("sipgate-mcp will store the PAT in macOS Keychain. Secret values are not written to MCP configuration or shell history.\n");
|
|
114
|
+
try {
|
|
115
|
+
storeCredentialsInteractively();
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
const message = error instanceof Error
|
|
119
|
+
? error.message
|
|
120
|
+
: "Secure credential storage failed.";
|
|
121
|
+
throw new SetupError(message);
|
|
122
|
+
}
|
|
123
|
+
for (const { client, registration } of commands) {
|
|
124
|
+
if (!isCommandAvailable(client)) {
|
|
125
|
+
process.stderr.write(`Skipping ${client}: command not found.\n`);
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
if (isAlreadyConfigured(client)) {
|
|
129
|
+
process.stderr.write(`Skipping ${client}: an MCP server named 'sipgate' is already configured. Remove it first to replace its launch command.\n`);
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
const result = spawnSync(registration.command, registration.args, {
|
|
133
|
+
stdio: "inherit",
|
|
134
|
+
});
|
|
135
|
+
if (result.error || result.status !== 0) {
|
|
136
|
+
throw new SetupError(`Could not register sipgate-mcp with ${client}.`);
|
|
137
|
+
}
|
|
138
|
+
process.stderr.write(`Registered sipgate-mcp with ${client} in user scope (${options.allowWrites ? "writes enabled" : "read-only"}).\n`);
|
|
139
|
+
}
|
|
140
|
+
process.stderr.write("Setup complete. Restart Codex or Claude, open /mcp, and ask it to list your sipgate numbers.\n");
|
|
141
|
+
}
|
|
142
|
+
export const SETUP_HELP = `Usage:
|
|
143
|
+
sipgate-mcp Start the MCP stdio server
|
|
144
|
+
sipgate-mcp setup [options] Store credentials and register MCP clients
|
|
145
|
+
sipgate-mcp --version Print the installed version
|
|
146
|
+
|
|
147
|
+
Setup options:
|
|
148
|
+
--client codex|claude Register only this client (repeatable)
|
|
149
|
+
--allow-writes Register write tools; default is read-only
|
|
150
|
+
--dry-run Print registration commands without changing anything
|
|
151
|
+
`;
|
|
152
|
+
//# sourceMappingURL=setup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,OAAO,UAAU,CAAC"}
|
package/dist/version.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sipgate-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "A self-hosted MCP server for configuring sipgate accounts through the sipgate REST API v2",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
},
|
|
17
17
|
"files": [
|
|
18
18
|
"dist",
|
|
19
|
+
"SKILL.md",
|
|
19
20
|
"README.md",
|
|
20
21
|
"CHANGELOG.md",
|
|
21
22
|
"LICENSE"
|