syncromsp-mcp 1.3.2 → 1.4.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/README.md +18 -19
- package/dist/auth.d.ts +13 -7
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +117 -23
- package/dist/auth.js.map +1 -1
- package/dist/index.js +21 -4
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,15 +4,17 @@ A fully-featured [Model Context Protocol](https://modelcontextprotocol.io) serve
|
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
-
- **170 API endpoints** across 15
|
|
8
|
-
- **
|
|
7
|
+
- **170 API endpoints** across 15 domains
|
|
8
|
+
- **Flat mode** (default) — all tools available immediately, works with Claude Desktop and Claude Code
|
|
9
|
+
- **Navigation mode** (optional) — lazy-loaded domains for lower token usage
|
|
9
10
|
- **Full CRUD** for tickets, customers, invoices, estimates, appointments, contracts, products, and more
|
|
10
11
|
- **Ticket comments** — email replies, public notes, and private/internal notes
|
|
11
12
|
- **Line items** — add products from catalog or manual entries to tickets, invoices, estimates, schedules
|
|
12
13
|
- **RMM alerts** — create, read, mute, resolve alerts on assets
|
|
13
14
|
- **Rate limiting** — built-in 180 req/min token bucket (Syncro API limit)
|
|
14
15
|
- **Confirmation required** for all destructive operations (DELETE, etc.)
|
|
15
|
-
- **Docker deployment** with
|
|
16
|
+
- **Docker deployment** with native MCP OAuth 2.1 for Claude.ai remote connection
|
|
17
|
+
- **Auto-update check** — warns on startup if a newer version is available
|
|
16
18
|
|
|
17
19
|
## Quick Start
|
|
18
20
|
|
|
@@ -83,21 +85,11 @@ Your subdomain is the part before `.syncromsp.com` in your Syncro URL (e.g., `my
|
|
|
83
85
|
|
|
84
86
|
## How It Works
|
|
85
87
|
|
|
86
|
-
###
|
|
88
|
+
### Tool Modes
|
|
87
89
|
|
|
88
|
-
|
|
90
|
+
**Flat mode** (default, `MCP_TOOL_MODE=flat`): All 170 tools are registered at startup. Works with all MCP clients including Claude Desktop and Claude Code.
|
|
89
91
|
|
|
90
|
-
|
|
91
|
-
Startup → 3 tools visible:
|
|
92
|
-
syncro_navigate("tickets") → loads ticket tools
|
|
93
|
-
syncro_status() → shows current domain
|
|
94
|
-
syncro_back() → returns to root
|
|
95
|
-
|
|
96
|
-
After navigating to "tickets" → domain tools visible:
|
|
97
|
-
tickets_list, tickets_get, tickets_create, tickets_update,
|
|
98
|
-
tickets_delete, tickets_comment, tickets_add_line_item, ...
|
|
99
|
-
syncro_back()
|
|
100
|
-
```
|
|
92
|
+
**Navigation mode** (`MCP_TOOL_MODE=navigation`): Uses a lazy-loading pattern — start with 3 navigation tools, then load domain-specific tools on demand. Lower token usage but requires client support for dynamic tool lists (works with Claude Code, not Claude Desktop).
|
|
101
93
|
|
|
102
94
|
### Available Domains
|
|
103
95
|
|
|
@@ -128,14 +120,17 @@ cp .env.example .env
|
|
|
128
120
|
# Edit .env with your Syncro credentials and base URL
|
|
129
121
|
```
|
|
130
122
|
|
|
131
|
-
|
|
123
|
+
Configure your `.env`:
|
|
132
124
|
|
|
133
125
|
```bash
|
|
134
126
|
SYNCRO_API_KEY=your-api-key
|
|
135
127
|
SYNCRO_SUBDOMAIN=your-subdomain
|
|
136
128
|
MCP_BASE_URL=https://mcp.yourcompany.com
|
|
129
|
+
MCP_AUTH_SECRET=your-strong-secret-here # Required! Users must know this to connect
|
|
137
130
|
```
|
|
138
131
|
|
|
132
|
+
Generate a strong secret: `openssl rand -hex 32`
|
|
133
|
+
|
|
139
134
|
Then deploy:
|
|
140
135
|
|
|
141
136
|
```bash
|
|
@@ -147,14 +142,17 @@ docker compose up -d
|
|
|
147
142
|
1. Deploy the server with HTTPS (via reverse proxy like Traefik, Caddy, or nginx)
|
|
148
143
|
2. In Claude.ai, go to **Settings** > **MCP Servers** > **Add Remote Server**
|
|
149
144
|
3. Enter your MCP URL: `https://mcp.yourcompany.com/mcp`
|
|
150
|
-
4. Claude.ai will auto-discover the OAuth endpoints
|
|
145
|
+
4. Claude.ai will auto-discover the OAuth endpoints
|
|
146
|
+
5. You'll be shown a login page — enter the `MCP_AUTH_SECRET` you configured
|
|
147
|
+
6. Once authenticated, Claude.ai gets a bearer token and connects
|
|
151
148
|
|
|
152
149
|
The server implements the full MCP OAuth 2.1 + PKCE spec:
|
|
153
150
|
- `/.well-known/oauth-authorization-server` — discovery metadata
|
|
154
|
-
- `/authorize` —
|
|
151
|
+
- `/authorize` — shows login page requiring the access key (`MCP_AUTH_SECRET`)
|
|
155
152
|
- `/token` — token endpoint with PKCE S256 validation
|
|
156
153
|
- `/register` — dynamic client registration (RFC 7591)
|
|
157
154
|
- Bearer token validation on all MCP requests
|
|
155
|
+
- **Connections without the correct access key are rejected**
|
|
158
156
|
|
|
159
157
|
### Disabling Auth
|
|
160
158
|
|
|
@@ -174,6 +172,7 @@ MCP_AUTH=false docker compose up -d
|
|
|
174
172
|
| `MCP_PORT` | No | HTTP port (default: `8080`) |
|
|
175
173
|
| `MCP_BASE_URL` | For OAuth | Public HTTPS URL (e.g., `https://mcp.yourcompany.com`) |
|
|
176
174
|
| `MCP_AUTH` | No | `true` (default) or `false` to disable OAuth |
|
|
175
|
+
| `MCP_AUTH_SECRET` | For OAuth | Access key users must enter to authorize (min 8 chars) |
|
|
177
176
|
| `MCP_TOOL_MODE` | No | `flat` (default, all tools) or `navigation` (lazy domains) |
|
|
178
177
|
|
|
179
178
|
## API Rate Limits
|
package/dist/auth.d.ts
CHANGED
|
@@ -9,22 +9,28 @@ declare class InMemoryClientsStore implements OAuthRegisteredClientsStore {
|
|
|
9
9
|
registerClient(clientMetadata: OAuthClientInformationFull): Promise<OAuthClientInformationFull>;
|
|
10
10
|
}
|
|
11
11
|
/**
|
|
12
|
-
* OAuth provider for MCP server authentication.
|
|
12
|
+
* Secure OAuth provider for MCP server authentication.
|
|
13
13
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
14
|
+
* When MCP_AUTH_SECRET is set, the authorize flow presents a login page
|
|
15
|
+
* requiring the secret before granting access. This prevents unauthorized
|
|
16
|
+
* clients from completing the OAuth flow even if they discover the server URL.
|
|
16
17
|
*
|
|
17
|
-
*
|
|
18
|
-
* deployed this themselves with their Syncro API key, any client that
|
|
19
|
-
* can reach the server and complete the OAuth flow is authorized.
|
|
18
|
+
* Without MCP_AUTH_SECRET, the server refuses to start in auth mode.
|
|
20
19
|
*/
|
|
21
20
|
export declare class McpOAuthProvider implements OAuthServerProvider {
|
|
22
21
|
readonly clientsStore: InMemoryClientsStore;
|
|
23
22
|
private readonly codes;
|
|
24
23
|
private readonly tokens;
|
|
24
|
+
private readonly pendingAuths;
|
|
25
25
|
private readonly tokenLifetimeMs;
|
|
26
|
-
|
|
26
|
+
private readonly authSecret;
|
|
27
|
+
constructor(authSecret: string, tokenLifetimeHours?: number);
|
|
27
28
|
authorize(client: OAuthClientInformationFull, params: AuthorizationParams, res: Response): Promise<void>;
|
|
29
|
+
/**
|
|
30
|
+
* Called from the /authorize/callback POST handler.
|
|
31
|
+
* Validates the secret and either redirects with an auth code or shows an error.
|
|
32
|
+
*/
|
|
33
|
+
handleAuthCallback(pendingId: string, secret: string, res: Response): Promise<void>;
|
|
28
34
|
challengeForAuthorizationCode(_client: OAuthClientInformationFull, authorizationCode: string): Promise<string>;
|
|
29
35
|
exchangeAuthorizationCode(client: OAuthClientInformationFull, authorizationCode: string, _codeVerifier?: string): Promise<OAuthTokens>;
|
|
30
36
|
exchangeRefreshToken(client: OAuthClientInformationFull, refreshToken: string, _scopes?: string[], _resource?: URL): Promise<OAuthTokens>;
|
package/dist/auth.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,mBAAmB,EACnB,mBAAmB,EACpB,MAAM,mDAAmD,CAAC;AAC3D,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,kDAAkD,CAAC;AACpG,OAAO,KAAK,EACV,0BAA0B,EAC1B,WAAW,EACZ,MAAM,0CAA0C,CAAC;AAClD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gDAAgD,CAAC;AAC/E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,mBAAmB,EACnB,mBAAmB,EACpB,MAAM,mDAAmD,CAAC;AAC3D,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,kDAAkD,CAAC;AACpG,OAAO,KAAK,EACV,0BAA0B,EAC1B,WAAW,EACZ,MAAM,0CAA0C,CAAC;AAClD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gDAAgD,CAAC;AAC/E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AA4BxC,cAAM,oBAAqB,YAAW,2BAA2B;IAC/D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiD;IAEnE,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,0BAA0B,GAAG,SAAS,CAAC;IAI5E,cAAc,CAClB,cAAc,EAAE,0BAA0B,GACzC,OAAO,CAAC,0BAA0B,CAAC;CAIvC;AAED;;;;;;;;GAQG;AACH,qBAAa,gBAAiB,YAAW,mBAAmB;IAC1D,QAAQ,CAAC,YAAY,uBAA8B;IACnD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA+B;IACrD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgC;IACvD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAkC;IAC/D,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;gBAExB,UAAU,EAAE,MAAM,EAAE,kBAAkB,GAAE,MAAW;IAUzD,SAAS,CACb,MAAM,EAAE,0BAA0B,EAClC,MAAM,EAAE,mBAAmB,EAC3B,GAAG,EAAE,QAAQ,GACZ,OAAO,CAAC,IAAI,CAAC;IAqDhB;;;OAGG;IACG,kBAAkB,CACtB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,QAAQ,GACZ,OAAO,CAAC,IAAI,CAAC;IAmDV,6BAA6B,CACjC,OAAO,EAAE,0BAA0B,EACnC,iBAAiB,EAAE,MAAM,GACxB,OAAO,CAAC,MAAM,CAAC;IAQZ,yBAAyB,CAC7B,MAAM,EAAE,0BAA0B,EAClC,iBAAiB,EAAE,MAAM,EACzB,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,WAAW,CAAC;IA6CjB,oBAAoB,CACxB,MAAM,EAAE,0BAA0B,EAClC,YAAY,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE,MAAM,EAAE,EAClB,SAAS,CAAC,EAAE,GAAG,GACd,OAAO,CAAC,WAAW,CAAC;IA2BjB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;IAcnD,WAAW,CACf,OAAO,EAAE,0BAA0B,EACnC,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,GACzB,OAAO,CAAC,IAAI,CAAC;CAGjB"}
|
package/dist/auth.js
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import { randomUUID } from "node:crypto";
|
|
1
|
+
import { randomUUID, createHash, timingSafeEqual } from "node:crypto";
|
|
2
|
+
function safeCompare(a, b) {
|
|
3
|
+
const hashA = createHash("sha256").update(a).digest();
|
|
4
|
+
const hashB = createHash("sha256").update(b).digest();
|
|
5
|
+
return timingSafeEqual(hashA, hashB);
|
|
6
|
+
}
|
|
2
7
|
class InMemoryClientsStore {
|
|
3
8
|
clients = new Map();
|
|
4
9
|
async getClient(clientId) {
|
|
@@ -10,40 +15,126 @@ class InMemoryClientsStore {
|
|
|
10
15
|
}
|
|
11
16
|
}
|
|
12
17
|
/**
|
|
13
|
-
* OAuth provider for MCP server authentication.
|
|
18
|
+
* Secure OAuth provider for MCP server authentication.
|
|
14
19
|
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
20
|
+
* When MCP_AUTH_SECRET is set, the authorize flow presents a login page
|
|
21
|
+
* requiring the secret before granting access. This prevents unauthorized
|
|
22
|
+
* clients from completing the OAuth flow even if they discover the server URL.
|
|
17
23
|
*
|
|
18
|
-
*
|
|
19
|
-
* deployed this themselves with their Syncro API key, any client that
|
|
20
|
-
* can reach the server and complete the OAuth flow is authorized.
|
|
24
|
+
* Without MCP_AUTH_SECRET, the server refuses to start in auth mode.
|
|
21
25
|
*/
|
|
22
26
|
export class McpOAuthProvider {
|
|
23
27
|
clientsStore = new InMemoryClientsStore();
|
|
24
28
|
codes = new Map();
|
|
25
29
|
tokens = new Map();
|
|
30
|
+
pendingAuths = new Map();
|
|
26
31
|
tokenLifetimeMs;
|
|
27
|
-
|
|
32
|
+
authSecret;
|
|
33
|
+
constructor(authSecret, tokenLifetimeHours = 24) {
|
|
34
|
+
if (!authSecret || authSecret.length < 8) {
|
|
35
|
+
throw new Error("MCP_AUTH_SECRET must be set and at least 8 characters for secure operation");
|
|
36
|
+
}
|
|
37
|
+
this.authSecret = authSecret;
|
|
28
38
|
this.tokenLifetimeMs = tokenLifetimeHours * 60 * 60 * 1000;
|
|
29
39
|
}
|
|
30
40
|
async authorize(client, params, res) {
|
|
31
|
-
//
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
41
|
+
// Store the pending auth and show login page
|
|
42
|
+
const pendingId = randomUUID();
|
|
43
|
+
this.pendingAuths.set(pendingId, {
|
|
44
|
+
client,
|
|
45
|
+
params,
|
|
46
|
+
createdAt: Date.now(),
|
|
47
|
+
});
|
|
48
|
+
// Clean up expired pending auths (older than 10 minutes)
|
|
36
49
|
const cutoff = Date.now() - 10 * 60 * 1000;
|
|
37
|
-
for (const [key, value] of this.
|
|
38
|
-
if (
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
50
|
+
for (const [key, value] of this.pendingAuths) {
|
|
51
|
+
if (value.createdAt < cutoff)
|
|
52
|
+
this.pendingAuths.delete(key);
|
|
53
|
+
}
|
|
54
|
+
// Serve a login page that requires the auth secret
|
|
55
|
+
res.setHeader("Content-Type", "text/html");
|
|
56
|
+
res.send(`<!DOCTYPE html>
|
|
57
|
+
<html>
|
|
58
|
+
<head>
|
|
59
|
+
<title>SyncroMSP MCP - Authorize</title>
|
|
60
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
61
|
+
<style>
|
|
62
|
+
body { font-family: -apple-system, system-ui, sans-serif; display: flex; justify-content: center; align-items: center; min-height: 100vh; margin: 0; background: #0f172a; color: #e2e8f0; }
|
|
63
|
+
.card { background: #1e293b; padding: 2rem; border-radius: 12px; max-width: 400px; width: 90%; box-shadow: 0 4px 24px rgba(0,0,0,0.3); }
|
|
64
|
+
h1 { font-size: 1.25rem; margin: 0 0 0.5rem; color: #f8fafc; }
|
|
65
|
+
p { font-size: 0.875rem; color: #94a3b8; margin: 0 0 1.5rem; }
|
|
66
|
+
label { display: block; font-size: 0.875rem; margin-bottom: 0.5rem; color: #cbd5e1; }
|
|
67
|
+
input[type="password"] { width: 100%; padding: 0.75rem; border: 1px solid #334155; border-radius: 8px; background: #0f172a; color: #f8fafc; font-size: 1rem; box-sizing: border-box; }
|
|
68
|
+
input[type="password"]:focus { outline: none; border-color: #3b82f6; box-shadow: 0 0 0 3px rgba(59,130,246,0.2); }
|
|
69
|
+
button { width: 100%; padding: 0.75rem; background: #3b82f6; color: white; border: none; border-radius: 8px; font-size: 1rem; cursor: pointer; margin-top: 1rem; }
|
|
70
|
+
button:hover { background: #2563eb; }
|
|
71
|
+
.error { color: #f87171; font-size: 0.875rem; margin-top: 0.5rem; display: none; }
|
|
72
|
+
.client-info { font-size: 0.75rem; color: #64748b; margin-top: 1rem; padding-top: 1rem; border-top: 1px solid #334155; }
|
|
73
|
+
</style>
|
|
74
|
+
</head>
|
|
75
|
+
<body>
|
|
76
|
+
<div class="card">
|
|
77
|
+
<h1>SyncroMSP MCP Server</h1>
|
|
78
|
+
<p>Enter the server access key to authorize this connection.</p>
|
|
79
|
+
<form method="POST" action="/authorize/callback">
|
|
80
|
+
<input type="hidden" name="pending_id" value="${pendingId}">
|
|
81
|
+
<label for="secret">Access Key</label>
|
|
82
|
+
<input type="password" id="secret" name="secret" placeholder="Enter MCP_AUTH_SECRET" required autofocus>
|
|
83
|
+
<div class="error" id="error">Invalid access key. Please try again.</div>
|
|
84
|
+
<button type="submit">Authorize</button>
|
|
85
|
+
</form>
|
|
86
|
+
<div class="client-info">Client: ${client.client_name || client.client_id}</div>
|
|
87
|
+
</div>
|
|
88
|
+
</body>
|
|
89
|
+
</html>`);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Called from the /authorize/callback POST handler.
|
|
93
|
+
* Validates the secret and either redirects with an auth code or shows an error.
|
|
94
|
+
*/
|
|
95
|
+
async handleAuthCallback(pendingId, secret, res) {
|
|
96
|
+
const pending = this.pendingAuths.get(pendingId);
|
|
97
|
+
if (!pending) {
|
|
98
|
+
res.status(400).send("Authorization request expired. Please try again.");
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
// Timing-safe comparison of the secret
|
|
102
|
+
if (!safeCompare(secret, this.authSecret)) {
|
|
103
|
+
// Re-show the form with error
|
|
104
|
+
this.pendingAuths.delete(pendingId);
|
|
105
|
+
res.status(403).send(`<!DOCTYPE html>
|
|
106
|
+
<html>
|
|
107
|
+
<head>
|
|
108
|
+
<title>Access Denied</title>
|
|
109
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
110
|
+
<style>
|
|
111
|
+
body { font-family: -apple-system, system-ui, sans-serif; display: flex; justify-content: center; align-items: center; min-height: 100vh; margin: 0; background: #0f172a; color: #e2e8f0; }
|
|
112
|
+
.card { background: #1e293b; padding: 2rem; border-radius: 12px; max-width: 400px; width: 90%; text-align: center; }
|
|
113
|
+
h1 { color: #f87171; font-size: 1.25rem; }
|
|
114
|
+
p { color: #94a3b8; }
|
|
115
|
+
</style>
|
|
116
|
+
</head>
|
|
117
|
+
<body>
|
|
118
|
+
<div class="card">
|
|
119
|
+
<h1>Access Denied</h1>
|
|
120
|
+
<p>Invalid access key. Connection rejected.</p>
|
|
121
|
+
</div>
|
|
122
|
+
</body>
|
|
123
|
+
</html>`);
|
|
124
|
+
return;
|
|
42
125
|
}
|
|
43
|
-
|
|
126
|
+
// Secret valid — issue auth code
|
|
127
|
+
this.pendingAuths.delete(pendingId);
|
|
128
|
+
const code = randomUUID();
|
|
129
|
+
this.codes.set(code, {
|
|
130
|
+
client: pending.client,
|
|
131
|
+
params: pending.params,
|
|
132
|
+
createdAt: Date.now(),
|
|
133
|
+
});
|
|
134
|
+
const redirectUrl = new URL(pending.params.redirectUri);
|
|
44
135
|
redirectUrl.searchParams.set("code", code);
|
|
45
|
-
if (params.state !== undefined) {
|
|
46
|
-
redirectUrl.searchParams.set("state", params.state);
|
|
136
|
+
if (pending.params.state !== undefined) {
|
|
137
|
+
redirectUrl.searchParams.set("state", pending.params.state);
|
|
47
138
|
}
|
|
48
139
|
res.redirect(redirectUrl.toString());
|
|
49
140
|
}
|
|
@@ -62,6 +153,11 @@ export class McpOAuthProvider {
|
|
|
62
153
|
if (codeData.client.client_id !== client.client_id) {
|
|
63
154
|
throw new Error("Authorization code was not issued to this client");
|
|
64
155
|
}
|
|
156
|
+
// Auth codes expire after 10 minutes
|
|
157
|
+
if (Date.now() - codeData.createdAt > 10 * 60 * 1000) {
|
|
158
|
+
this.codes.delete(authorizationCode);
|
|
159
|
+
throw new Error("Authorization code expired");
|
|
160
|
+
}
|
|
65
161
|
this.codes.delete(authorizationCode);
|
|
66
162
|
const accessToken = randomUUID();
|
|
67
163
|
const refreshToken = randomUUID();
|
|
@@ -72,7 +168,6 @@ export class McpOAuthProvider {
|
|
|
72
168
|
expiresAt: Date.now() + this.tokenLifetimeMs,
|
|
73
169
|
resource: codeData.params.resource,
|
|
74
170
|
});
|
|
75
|
-
// Store refresh token with longer lifetime (30 days)
|
|
76
171
|
this.tokens.set(refreshToken, {
|
|
77
172
|
token: refreshToken,
|
|
78
173
|
clientId: client.client_id,
|
|
@@ -96,7 +191,6 @@ export class McpOAuthProvider {
|
|
|
96
191
|
if (tokenData.clientId !== client.client_id) {
|
|
97
192
|
throw new Error("Refresh token was not issued to this client");
|
|
98
193
|
}
|
|
99
|
-
// Issue new access token
|
|
100
194
|
const newAccessToken = randomUUID();
|
|
101
195
|
this.tokens.set(newAccessToken, {
|
|
102
196
|
token: newAccessToken,
|
package/dist/auth.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -28,36 +28,53 @@ if (transport === "http") {
|
|
|
28
28
|
const { isInitializeRequest } = await import("@modelcontextprotocol/sdk/types.js");
|
|
29
29
|
const port = parseInt(process.env.MCP_PORT || "8080", 10);
|
|
30
30
|
const useAuth = process.env.MCP_AUTH !== "false";
|
|
31
|
+
const authSecret = process.env.MCP_AUTH_SECRET;
|
|
31
32
|
const baseUrl = process.env.MCP_BASE_URL || `http://localhost:${port}`;
|
|
32
33
|
const mcpServerUrl = new URL(baseUrl);
|
|
34
|
+
if (useAuth && !authSecret) {
|
|
35
|
+
console.error("ERROR: MCP_AUTH_SECRET is required when auth is enabled.\n" +
|
|
36
|
+
" Set MCP_AUTH_SECRET to a strong secret (min 8 chars) in your environment.\n" +
|
|
37
|
+
" Or set MCP_AUTH=false to disable auth (not recommended for public deployments).");
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
33
40
|
const app = express();
|
|
34
41
|
app.use(express.json());
|
|
42
|
+
app.use(express.urlencoded({ extended: false }));
|
|
35
43
|
// Health check (always unauthenticated)
|
|
36
44
|
app.get("/health", (_req, res) => {
|
|
37
45
|
res.json({ status: "ok", transport: "http", auth: useAuth });
|
|
38
46
|
});
|
|
39
47
|
let authMiddleware;
|
|
40
|
-
if (useAuth) {
|
|
48
|
+
if (useAuth && authSecret) {
|
|
41
49
|
const { McpOAuthProvider } = await import("./auth.js");
|
|
42
50
|
const { mcpAuthRouter } = await import("@modelcontextprotocol/sdk/server/auth/router.js");
|
|
43
51
|
const { requireBearerAuth } = await import("@modelcontextprotocol/sdk/server/auth/middleware/bearerAuth.js");
|
|
44
52
|
const { getOAuthProtectedResourceMetadataUrl } = await import("@modelcontextprotocol/sdk/server/auth/router.js");
|
|
45
|
-
const oauthProvider = new McpOAuthProvider();
|
|
53
|
+
const oauthProvider = new McpOAuthProvider(authSecret);
|
|
46
54
|
// Install OAuth routes (/.well-known/*, /authorize, /token, /register, /revoke)
|
|
47
55
|
app.use(mcpAuthRouter({
|
|
48
56
|
provider: oauthProvider,
|
|
49
57
|
issuerUrl: mcpServerUrl,
|
|
50
58
|
scopesSupported: ["mcp:tools"],
|
|
51
59
|
}));
|
|
60
|
+
// Handle the auth secret validation callback
|
|
61
|
+
app.post("/authorize/callback", async (req, res) => {
|
|
62
|
+
const { pending_id, secret } = req.body;
|
|
63
|
+
if (!pending_id || !secret) {
|
|
64
|
+
res.status(400).send("Missing required fields");
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
await oauthProvider.handleAuthCallback(pending_id, secret, res);
|
|
68
|
+
});
|
|
52
69
|
authMiddleware = requireBearerAuth({
|
|
53
70
|
verifier: oauthProvider,
|
|
54
71
|
requiredScopes: [],
|
|
55
72
|
resourceMetadataUrl: getOAuthProtectedResourceMetadataUrl(mcpServerUrl),
|
|
56
73
|
});
|
|
57
|
-
console.error(`OAuth enabled. Issuer: ${mcpServerUrl}`);
|
|
74
|
+
console.error(`OAuth enabled with access key. Issuer: ${mcpServerUrl}`);
|
|
58
75
|
}
|
|
59
76
|
else {
|
|
60
|
-
console.error("Auth disabled (MCP_AUTH=false)");
|
|
77
|
+
console.error("Auth disabled (MCP_AUTH=false). WARNING: Server is unprotected.");
|
|
61
78
|
}
|
|
62
79
|
// Session management
|
|
63
80
|
const transports = {};
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAiB,MAAM,aAAa,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAE3D,uCAAuC;AACvC,eAAe,EAAE,CAAC;AAElB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;AAC1C,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;AAE/C,IAAI,CAAC,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC;IAC1B,OAAO,CAAC,KAAK,CACX,2CAA2C;QACzC,kEAAkE;QAClE,8FAA8F,CACjG,CAAC;IACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,2EAA2E;AAC3E,4EAA4E;AAC5E,iDAAiD;AACjD,6CAA6C;AAC7C,MAAM,QAAQ,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,MAAM,CAAa,CAAC;AAEnE,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;AAC1D,MAAM,SAAS,GAAG,YAAY,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;AAEjD,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,OAAO,CAAC;AAEvD,IAAI,SAAS,KAAK,MAAM,EAAE,CAAC;IACzB,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,CAAC;IACrD,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC;IACnD,MAAM,EAAE,6BAA6B,EAAE,GAAG,MAAM,MAAM,CACpD,oDAAoD,CACrD,CAAC;IACF,MAAM,EAAE,mBAAmB,EAAE,GAAG,MAAM,MAAM,CAC1C,oCAAoC,CACrC,CAAC;IAEF,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,MAAM,EAAE,EAAE,CAAC,CAAC;IAC1D,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,OAAO,CAAC;IACjD,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,oBAAoB,IAAI,EAAE,CAAC;IACvE,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;IAEtC,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;IACtB,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED