@briefgate/mcp 0.7.4 → 0.7.5
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 +118 -19
- package/dist/client.d.ts +8 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +6 -1
- package/dist/client.js.map +1 -1
- package/dist/credentials.d.ts +31 -0
- package/dist/credentials.d.ts.map +1 -0
- package/dist/credentials.js +89 -0
- package/dist/credentials.js.map +1 -0
- package/dist/device-auth.d.ts +41 -0
- package/dist/device-auth.d.ts.map +1 -0
- package/dist/device-auth.js +119 -0
- package/dist/device-auth.js.map +1 -0
- package/dist/http-auth.d.ts +39 -5
- package/dist/http-auth.d.ts.map +1 -1
- package/dist/http-auth.js +63 -7
- package/dist/http-auth.js.map +1 -1
- package/dist/index.js +390 -187
- package/dist/index.js.map +1 -1
- package/dist/login.d.ts +49 -0
- package/dist/login.d.ts.map +1 -0
- package/dist/login.js +205 -0
- package/dist/login.js.map +1 -0
- package/dist/tools.d.ts +65 -5
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +87 -2
- package/dist/tools.js.map +1 -1
- package/package.json +1 -1
package/dist/http-auth.d.ts
CHANGED
|
@@ -3,7 +3,9 @@ import type { BriefGateConfig } from './client.js';
|
|
|
3
3
|
export interface HttpAuthOptions {
|
|
4
4
|
/** Hostname this server is published under, or undefined when it is loopback-only. */
|
|
5
5
|
publicHost?: string | undefined;
|
|
6
|
-
/**
|
|
6
|
+
/** The operator's own key, from --api-key, used only when NOT published. */
|
|
7
|
+
cliApiKey?: string | undefined;
|
|
8
|
+
/** The operator's own key, from BRIEFGATE_API_KEY, used only when NOT published. */
|
|
7
9
|
envApiKey?: string | undefined;
|
|
8
10
|
baseUrl: string;
|
|
9
11
|
}
|
|
@@ -11,13 +13,17 @@ export interface HttpAuthOptions {
|
|
|
11
13
|
* The API key for one request.
|
|
12
14
|
*
|
|
13
15
|
* Published mode reads it from the Authorization header and nowhere else. The
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
16
|
+
* --api-key / environment / locally-stored-credential fallbacks exist so a
|
|
17
|
+
* laptop can run `--http` against the operator's own key (or one saved by
|
|
18
|
+
* `login`); on a public endpoint any of those would hand that key to whoever
|
|
19
|
+
* asked first, so all three are switched off there rather than merely
|
|
20
|
+
* discouraged.
|
|
17
21
|
*
|
|
18
22
|
* An absent key is not an error here. `initialize` and `tools/list` have to work
|
|
19
23
|
* without one, or no registry can read the tool list before anybody signs up —
|
|
20
|
-
* a tool call with no key fails later with a sentence saying so.
|
|
24
|
+
* a tool call with no key fails later with a sentence saying so. Published
|
|
25
|
+
* mode is stricter about this at the HTTP layer (see index.ts): a request with
|
|
26
|
+
* no Bearer token never reaches this function at all.
|
|
21
27
|
*/
|
|
22
28
|
export declare function configForRequest(req: IncomingMessage, opts: HttpAuthOptions): BriefGateConfig;
|
|
23
29
|
/**
|
|
@@ -27,5 +33,33 @@ export declare function configForRequest(req: IncomingMessage, opts: HttpAuthOpt
|
|
|
27
33
|
* pointed at this box by whoever noticed the IP.
|
|
28
34
|
*/
|
|
29
35
|
export declare function isAllowedHost(host: string, publicHost?: string | undefined): boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Published mode allows any origin: the resource is protected by the Bearer
|
|
38
|
+
* token, which — unlike a cookie — a browser never attaches on its own, so
|
|
39
|
+
* restricting origins buys no extra security and would only stop legitimate
|
|
40
|
+
* OAuth-registered clients (claude.ai and others) from connecting. Loopback
|
|
41
|
+
* mode keeps the strict allowlist: there, a plain `--http` run may still be
|
|
42
|
+
* relying on an operator key with no per-request Bearer at all, so the origin
|
|
43
|
+
* check is doing real work.
|
|
44
|
+
*/
|
|
30
45
|
export declare function isAllowedOrigin(origin: string, publicHost?: string | undefined): boolean;
|
|
46
|
+
export declare const WELL_KNOWN_PROTECTED_RESOURCE_PATH = "/.well-known/oauth-protected-resource";
|
|
47
|
+
export declare const WELL_KNOWN_PROTECTED_RESOURCE_MCP_PATH = "/.well-known/oauth-protected-resource/mcp";
|
|
48
|
+
export interface ProtectedResourceMetadata {
|
|
49
|
+
resource: string;
|
|
50
|
+
authorization_servers: string[];
|
|
51
|
+
bearer_methods_supported: string[];
|
|
52
|
+
scopes_supported: string[];
|
|
53
|
+
resource_name: string;
|
|
54
|
+
}
|
|
55
|
+
export declare function protectedResourceMetadata(publicHost: string, authServer: string): ProtectedResourceMetadata;
|
|
56
|
+
/**
|
|
57
|
+
* Value for the `WWW-Authenticate` header on a 401, pointing the client at
|
|
58
|
+
* the resource metadata above so it knows where to start the OAuth dance.
|
|
59
|
+
* Pass `error: 'invalid_token'` when the caller did send a Bearer token and
|
|
60
|
+
* it was specifically rejected (expired/revoked) — as opposed to no token
|
|
61
|
+
* having been sent at all — so the client knows to refresh rather than just
|
|
62
|
+
* retry the same one.
|
|
63
|
+
*/
|
|
64
|
+
export declare function wwwAuthenticateHeader(publicHost: string, error?: 'invalid_token'): string;
|
|
31
65
|
//# sourceMappingURL=http-auth.d.ts.map
|
package/dist/http-auth.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http-auth.d.ts","sourceRoot":"","sources":["../src/http-auth.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"http-auth.d.ts","sourceRoot":"","sources":["../src/http-auth.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAGnD,MAAM,WAAW,eAAe;IAC9B,sFAAsF;IACtF,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,4EAA4E;IAC5E,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,oFAAoF;IACpF,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE,eAAe,GAAG,eAAe,CAkB7F;AAID;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAIpF;AAMD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAGxF;AAWD,eAAO,MAAM,kCAAkC,0CAA0C,CAAC;AAC1F,eAAO,MAAM,sCAAsC,8CAA8C,CAAC;AAElG,MAAM,WAAW,yBAAyB;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,qBAAqB,EAAE,MAAM,EAAE,CAAC;IAChC,wBAAwB,EAAE,MAAM,EAAE,CAAC;IACnC,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,yBAAyB,CACvC,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACjB,yBAAyB,CAQ3B;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,eAAe,GAAG,MAAM,CAGzF"}
|
package/dist/http-auth.js
CHANGED
|
@@ -1,20 +1,36 @@
|
|
|
1
|
+
import { resolveApiKey } from './credentials.js';
|
|
1
2
|
/**
|
|
2
3
|
* The API key for one request.
|
|
3
4
|
*
|
|
4
5
|
* Published mode reads it from the Authorization header and nowhere else. The
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
6
|
+
* --api-key / environment / locally-stored-credential fallbacks exist so a
|
|
7
|
+
* laptop can run `--http` against the operator's own key (or one saved by
|
|
8
|
+
* `login`); on a public endpoint any of those would hand that key to whoever
|
|
9
|
+
* asked first, so all three are switched off there rather than merely
|
|
10
|
+
* discouraged.
|
|
8
11
|
*
|
|
9
12
|
* An absent key is not an error here. `initialize` and `tools/list` have to work
|
|
10
13
|
* without one, or no registry can read the tool list before anybody signs up —
|
|
11
|
-
* a tool call with no key fails later with a sentence saying so.
|
|
14
|
+
* a tool call with no key fails later with a sentence saying so. Published
|
|
15
|
+
* mode is stricter about this at the HTTP layer (see index.ts): a request with
|
|
16
|
+
* no Bearer token never reaches this function at all.
|
|
12
17
|
*/
|
|
13
18
|
export function configForRequest(req, opts) {
|
|
14
19
|
const header = req.headers['authorization'];
|
|
15
20
|
const bearer = typeof header === 'string' ? /^Bearer\s+(\S+)$/i.exec(header.trim())?.[1] : undefined;
|
|
16
|
-
|
|
17
|
-
|
|
21
|
+
if (opts.publicHost) {
|
|
22
|
+
return { apiKey: bearer ?? '', baseUrl: opts.baseUrl, apiKeySource: bearer ? 'header' : 'none' };
|
|
23
|
+
}
|
|
24
|
+
if (bearer)
|
|
25
|
+
return { apiKey: bearer, baseUrl: opts.baseUrl, apiKeySource: 'header' };
|
|
26
|
+
const { apiKey, source } = resolveApiKey({
|
|
27
|
+
explicitApiKey: opts.cliApiKey,
|
|
28
|
+
explicitSource: 'flag',
|
|
29
|
+
envApiKey: opts.envApiKey,
|
|
30
|
+
baseUrl: opts.baseUrl,
|
|
31
|
+
allowFileFallback: true,
|
|
32
|
+
});
|
|
33
|
+
return { apiKey, baseUrl: opts.baseUrl, apiKeySource: source };
|
|
18
34
|
}
|
|
19
35
|
const LOOPBACK_HOST_RE = /^(?:localhost|127\.0\.0\.1|\[::1\])(?::\d+)?$/;
|
|
20
36
|
/**
|
|
@@ -31,9 +47,49 @@ export function isAllowedHost(host, publicHost) {
|
|
|
31
47
|
}
|
|
32
48
|
/** Loopback origins and claude.ai, which proxies MCP for its own clients. */
|
|
33
49
|
const SAFE_ORIGIN_RE = /^https?:\/\/(?:localhost|127\.0\.0\.1|\[::1\])(?::\d+)?$|^https:\/\/claude\.ai$/;
|
|
50
|
+
/**
|
|
51
|
+
* Published mode allows any origin: the resource is protected by the Bearer
|
|
52
|
+
* token, which — unlike a cookie — a browser never attaches on its own, so
|
|
53
|
+
* restricting origins buys no extra security and would only stop legitimate
|
|
54
|
+
* OAuth-registered clients (claude.ai and others) from connecting. Loopback
|
|
55
|
+
* mode keeps the strict allowlist: there, a plain `--http` run may still be
|
|
56
|
+
* relying on an operator key with no per-request Bearer at all, so the origin
|
|
57
|
+
* check is doing real work.
|
|
58
|
+
*/
|
|
34
59
|
export function isAllowedOrigin(origin, publicHost) {
|
|
35
|
-
if (publicHost
|
|
60
|
+
if (publicHost)
|
|
36
61
|
return true;
|
|
37
62
|
return SAFE_ORIGIN_RE.test(origin);
|
|
38
63
|
}
|
|
64
|
+
// ─── OAuth 2.1 protected-resource metadata (published mode only) ─────────────
|
|
65
|
+
//
|
|
66
|
+
// Lets an MCP client (claude.ai's connector UI) discover, from the server URL
|
|
67
|
+
// alone, which authorization server to run OAuth against — RFC 9728 as
|
|
68
|
+
// profiled by the MCP authorization spec.
|
|
69
|
+
// RFC 9728 defines the bare path; the MCP authorization spec also has clients
|
|
70
|
+
// look under a path scoped to the resource itself (the resource being `/mcp`
|
|
71
|
+
// here) — both must serve identical content.
|
|
72
|
+
export const WELL_KNOWN_PROTECTED_RESOURCE_PATH = '/.well-known/oauth-protected-resource';
|
|
73
|
+
export const WELL_KNOWN_PROTECTED_RESOURCE_MCP_PATH = `${WELL_KNOWN_PROTECTED_RESOURCE_PATH}/mcp`;
|
|
74
|
+
export function protectedResourceMetadata(publicHost, authServer) {
|
|
75
|
+
return {
|
|
76
|
+
resource: `https://${publicHost}/mcp`,
|
|
77
|
+
authorization_servers: [authServer],
|
|
78
|
+
bearer_methods_supported: ['header'],
|
|
79
|
+
scopes_supported: ['admin', 'intakes:read', 'intakes:write', 'secrets:read'],
|
|
80
|
+
resource_name: 'BriefGate MCP',
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Value for the `WWW-Authenticate` header on a 401, pointing the client at
|
|
85
|
+
* the resource metadata above so it knows where to start the OAuth dance.
|
|
86
|
+
* Pass `error: 'invalid_token'` when the caller did send a Bearer token and
|
|
87
|
+
* it was specifically rejected (expired/revoked) — as opposed to no token
|
|
88
|
+
* having been sent at all — so the client knows to refresh rather than just
|
|
89
|
+
* retry the same one.
|
|
90
|
+
*/
|
|
91
|
+
export function wwwAuthenticateHeader(publicHost, error) {
|
|
92
|
+
const resourceMetadata = `resource_metadata="https://${publicHost}${WELL_KNOWN_PROTECTED_RESOURCE_PATH}"`;
|
|
93
|
+
return error ? `Bearer error="${error}", ${resourceMetadata}` : `Bearer ${resourceMetadata}`;
|
|
94
|
+
}
|
|
39
95
|
//# sourceMappingURL=http-auth.js.map
|
package/dist/http-auth.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http-auth.js","sourceRoot":"","sources":["../src/http-auth.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"http-auth.js","sourceRoot":"","sources":["../src/http-auth.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAYjD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAoB,EAAE,IAAqB;IAC1E,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;IAC5C,MAAM,MAAM,GACV,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,mBAAmB,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAExF,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;QACpB,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IACnG,CAAC;IACD,IAAI,MAAM;QAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAC;IAErF,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,aAAa,CAAC;QACvC,cAAc,EAAE,IAAI,CAAC,SAAS;QAC9B,cAAc,EAAE,MAAM;QACtB,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,iBAAiB,EAAE,IAAI;KACxB,CAAC,CAAC;IACH,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,CAAC;AACjE,CAAC;AAED,MAAM,gBAAgB,GAAG,+CAA+C,CAAC;AAEzE;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,UAA+B;IACzE,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IAC5D,IAAI,UAAU,IAAI,WAAW,KAAK,UAAU,CAAC,WAAW,EAAE;QAAE,OAAO,IAAI,CAAC;IACxE,OAAO,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACrC,CAAC;AAED,6EAA6E;AAC7E,MAAM,cAAc,GAClB,iFAAiF,CAAC;AAEpF;;;;;;;;GAQG;AACH,MAAM,UAAU,eAAe,CAAC,MAAc,EAAE,UAA+B;IAC7E,IAAI,UAAU;QAAE,OAAO,IAAI,CAAC;IAC5B,OAAO,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AACrC,CAAC;AAED,gFAAgF;AAChF,EAAE;AACF,8EAA8E;AAC9E,uEAAuE;AACvE,0CAA0C;AAE1C,8EAA8E;AAC9E,6EAA6E;AAC7E,6CAA6C;AAC7C,MAAM,CAAC,MAAM,kCAAkC,GAAG,uCAAuC,CAAC;AAC1F,MAAM,CAAC,MAAM,sCAAsC,GAAG,GAAG,kCAAkC,MAAM,CAAC;AAUlG,MAAM,UAAU,yBAAyB,CACvC,UAAkB,EAClB,UAAkB;IAElB,OAAO;QACL,QAAQ,EAAE,WAAW,UAAU,MAAM;QACrC,qBAAqB,EAAE,CAAC,UAAU,CAAC;QACnC,wBAAwB,EAAE,CAAC,QAAQ,CAAC;QACpC,gBAAgB,EAAE,CAAC,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,cAAc,CAAC;QAC5E,aAAa,EAAE,eAAe;KAC/B,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,qBAAqB,CAAC,UAAkB,EAAE,KAAuB;IAC/E,MAAM,gBAAgB,GAAG,8BAA8B,UAAU,GAAG,kCAAkC,GAAG,CAAC;IAC1G,OAAO,KAAK,CAAC,CAAC,CAAC,iBAAiB,KAAK,MAAM,gBAAgB,EAAE,CAAC,CAAC,CAAC,UAAU,gBAAgB,EAAE,CAAC;AAC/F,CAAC"}
|