qyl-mcp-server 7.1.0 → 7.1.1
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 +47 -4
- package/dist/auth-extensions.d.ts +20 -0
- package/dist/auth-extensions.js +81 -0
- package/dist/auth-extensions.js.map +1 -0
- package/dist/auth.d.ts +4 -0
- package/dist/auth.js +5 -0
- package/dist/auth.js.map +1 -0
- package/dist/authorization.d.ts +14 -0
- package/dist/authorization.js +82 -0
- package/dist/authorization.js.map +1 -0
- package/dist/ci.js +2 -1
- package/dist/ci.js.map +1 -1
- package/dist/config.d.ts +2 -2
- package/dist/config.js +2 -2
- package/dist/config.js.map +1 -1
- package/dist/events-authorization.d.ts +9 -0
- package/dist/events-authorization.js +160 -0
- package/dist/events-authorization.js.map +1 -0
- package/dist/events.d.ts +234 -0
- package/dist/events.js +596 -0
- package/dist/events.js.map +1 -0
- package/dist/main.d.ts +11 -17
- package/dist/main.js +82 -29
- package/dist/main.js.map +1 -1
- package/dist/mcp-app.html +1 -1
- package/dist/mcp-dashboard.html +1 -1
- package/dist/mcp-home.html +4 -4
- package/dist/metrics-tools.js +4 -1
- package/dist/metrics-tools.js.map +1 -1
- package/dist/oauth-metadata.d.ts +8 -0
- package/dist/oauth-metadata.js +89 -0
- package/dist/oauth-metadata.js.map +1 -0
- package/dist/oauth.d.ts +7 -17
- package/dist/oauth.js +16 -68
- package/dist/oauth.js.map +1 -1
- package/dist/server.d.ts +6 -1
- package/dist/server.js +51 -12
- package/dist/server.js.map +1 -1
- package/dist/tools.d.ts +10 -0
- package/dist/tools.js +12 -0
- package/dist/tools.js.map +1 -1
- package/dist/webhook.d.ts +45 -0
- package/dist/webhook.js +198 -0
- package/dist/webhook.js.map +1 -0
- package/package.json +24 -20
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@ npx qyl-mcp-server --stdio # stdio MCP server
|
|
|
9
9
|
npx qyl-mcp-server # Streamable HTTP on 127.0.0.1:3001
|
|
10
10
|
```
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
Use a modern or 2025-era MCP client. Point it at a collector:
|
|
13
13
|
|
|
14
14
|
```bash
|
|
15
15
|
export QYL_COLLECTOR_URL=http://127.0.0.1:5100
|
|
@@ -24,12 +24,40 @@ It is an OAuth 2.1 resource server, so an unauthenticated request answers `401`
|
|
|
24
24
|
with an RFC 9728 protected-resource document that a stock MCP client follows on
|
|
25
25
|
its own.
|
|
26
26
|
|
|
27
|
-
Both
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
Both use MCP TypeScript SDK v2: Streamable HTTP through `createMcpHandler`
|
|
28
|
+
and stdio through `serveStdio`, with their documented compatibility defaults.
|
|
29
|
+
One factory serves revision `2026-07-28` and supported 2025-era requests.
|
|
30
|
+
Events require `2026-07-28`.
|
|
30
31
|
The HTTP server serves a product page at `/`; `/mcp` is the only protocol
|
|
31
32
|
endpoint.
|
|
32
33
|
|
|
34
|
+
## Hosted authentication
|
|
35
|
+
|
|
36
|
+
The hosted Auth0 profile requires CIMD and DCR discovery, Authorization Code
|
|
37
|
+
with PKCE S256, both `private_key_jwt` and `none` for ChatGPT CIMD compatibility,
|
|
38
|
+
`none` for Claude CIMD, and issuer identification. Auth0 owns registration and token
|
|
39
|
+
issuance; this server validates resource-bound RFC 9068 access tokens on every
|
|
40
|
+
MCP request. It rejects malformed/query credentials, invalid tokens and
|
|
41
|
+
insufficient scopes with distinct 400/401/403 responses.
|
|
42
|
+
|
|
43
|
+
Optional resource-server integrations are selected explicitly:
|
|
44
|
+
|
|
45
|
+
```sh
|
|
46
|
+
MCP_AUTH_EXTENSIONS=enterprise-managed-authorization@1.0.0,oauth-client-credentials@1.0.0
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Enterprise-managed authorization is stable upstream; client credentials is a
|
|
50
|
+
draft extension. Both preserve the core token verifier and require matching
|
|
51
|
+
Auth0 capabilities and separately provisioned client grants. Integration versions
|
|
52
|
+
are independent of the MCP wire version. Embedders can use the exported
|
|
53
|
+
`qyl-mcp-server/auth` composition API for additional declarative modules and
|
|
54
|
+
explicit scope hierarchies.
|
|
55
|
+
|
|
56
|
+
See the [deployment and authentication guide](https://github.com/ANcpLua/qyl.mcp#authentication)
|
|
57
|
+
for Auth0 configuration, extension responsibilities, and verification. Auth0
|
|
58
|
+
requires Enterprise for `private_key_jwt`. Neither a provider capability flag nor
|
|
59
|
+
an enabled module proves a client has been provisioned.
|
|
60
|
+
|
|
33
61
|
## Tools
|
|
34
62
|
|
|
35
63
|
**Telemetry** — `list_traces`, `get_trace`, `list_sessions`, `search_logs`,
|
|
@@ -85,6 +113,9 @@ multi-tenant audit log.
|
|
|
85
113
|
| `QYL_MCP_TELEMETRY=0` | Disable MCP spans, metrics, and operation logs. |
|
|
86
114
|
| `QYL_MCP_CAPTURE_CONTENT=1` | Include redacted, size-bounded request and response bodies in operation logs. Off by default. |
|
|
87
115
|
| `QYL_MCP_NATIVE_STATE_PATH` | Override the native execution-evidence path. |
|
|
116
|
+
| `MCP_EVENTS_STORE` | Persistent Events subscription file; requires Auth0 and the access-check credentials below. |
|
|
117
|
+
| `MCP_EVENTS_AUTH0_CLIENT_ID` / `MCP_EVENTS_AUTH0_CLIENT_SECRET` | Dedicated Management API application with `read:users`, `read:clients`, `read:client_grants`, `read:grants`; resolves CIMD identities and keeps access checks current without storing subscriber tokens. |
|
|
118
|
+
| `MCP_EVENTS_POLL_MS` | Collector polling interval, at least 5000 ms; default 30000 ms. |
|
|
88
119
|
| `PORT` | HTTP listener port; default `3001`. |
|
|
89
120
|
|
|
90
121
|
Secrets are redacted before results reach the model, structured content, or
|
|
@@ -96,6 +127,18 @@ so serving it requires Bun.
|
|
|
96
127
|
|
|
97
128
|
## Release notes
|
|
98
129
|
|
|
130
|
+
### 7.1.1
|
|
131
|
+
|
|
132
|
+
- SDK v2.3.1 serving defaults accept modern and 2025-era tool clients over HTTP
|
|
133
|
+
and stdio. The workbench negotiates automatically. The strict policy described
|
|
134
|
+
under 6.0.0 below has been removed.
|
|
135
|
+
- Events recheck account status, explicit client access, user permissions and
|
|
136
|
+
consent through Auth0. Unsubscribe aborts outstanding deliveries; restart
|
|
137
|
+
cleanup removes expired subscriptions and obsolete signing keys.
|
|
138
|
+
- Public viewers declare their deployment origin and keep the requested trace
|
|
139
|
+
limit on refresh. Release verification exercises a fresh npm consumer with
|
|
140
|
+
modern and 2025-era discovery and a real demo-tool call.
|
|
141
|
+
|
|
99
142
|
### 7.1.0
|
|
100
143
|
|
|
101
144
|
- The hosted server can sit behind Cloudflare Access Managed OAuth:
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { OAuthMetadata } from "@modelcontextprotocol/server";
|
|
2
|
+
/** Resource-server integrations, versioned separately from the MCP wire revision.
|
|
3
|
+
* Extensions declare provider requirements; they cannot replace token verification,
|
|
4
|
+
* mint tokens, rewrite discovery, or grant scopes to a caller.
|
|
5
|
+
*/
|
|
6
|
+
export interface AuthorizationExtension {
|
|
7
|
+
readonly id: string;
|
|
8
|
+
readonly version: string;
|
|
9
|
+
readonly stability: "stable" | "draft";
|
|
10
|
+
readonly specification: string;
|
|
11
|
+
readonly requirements: Readonly<Record<string, true | readonly string[]>>;
|
|
12
|
+
}
|
|
13
|
+
export declare const enterpriseManagedAuthorization: AuthorizationExtension;
|
|
14
|
+
export declare const clientCredentialsAuthorization: AuthorizationExtension;
|
|
15
|
+
export declare const authorizationExtensions: readonly AuthorizationExtension[];
|
|
16
|
+
/** Explicit version pins are mandatory, including for draft integrations. */
|
|
17
|
+
export declare function resolveAuthorizationExtensions(selections: readonly string[], available?: readonly AuthorizationExtension[]): readonly AuthorizationExtension[];
|
|
18
|
+
export declare function readAuthorizationExtensions(environment: Readonly<Record<string, string | undefined>>): readonly AuthorizationExtension[];
|
|
19
|
+
/** Union requirements deterministically; a composition can only add requirements. */
|
|
20
|
+
export declare function validateAuthorizationExtensions(metadata: OAuthMetadata, extensions: readonly AuthorizationExtension[]): void;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
export const enterpriseManagedAuthorization = {
|
|
2
|
+
id: "enterprise-managed-authorization",
|
|
3
|
+
version: "1.0.0",
|
|
4
|
+
stability: "stable",
|
|
5
|
+
specification: "https://github.com/modelcontextprotocol/ext-auth/blob/main/specification/stable/enterprise-managed-authorization.mdx",
|
|
6
|
+
requirements: {
|
|
7
|
+
grant_types_supported: ["urn:ietf:params:oauth:grant-type:jwt-bearer"],
|
|
8
|
+
authorization_grant_profiles_supported: ["urn:ietf:params:oauth:grant-profile:id-jag"],
|
|
9
|
+
},
|
|
10
|
+
};
|
|
11
|
+
export const clientCredentialsAuthorization = {
|
|
12
|
+
id: "oauth-client-credentials",
|
|
13
|
+
version: "1.0.0",
|
|
14
|
+
stability: "draft",
|
|
15
|
+
specification: "https://github.com/modelcontextprotocol/ext-auth/blob/main/specification/draft/oauth-client-credentials.mdx",
|
|
16
|
+
requirements: {
|
|
17
|
+
grant_types_supported: ["client_credentials"],
|
|
18
|
+
token_endpoint_auth_methods_supported: ["private_key_jwt"],
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
export const authorizationExtensions = [
|
|
22
|
+
enterpriseManagedAuthorization,
|
|
23
|
+
clientCredentialsAuthorization,
|
|
24
|
+
];
|
|
25
|
+
/** Explicit version pins are mandatory, including for draft integrations. */
|
|
26
|
+
export function resolveAuthorizationExtensions(selections, available = authorizationExtensions) {
|
|
27
|
+
const resolved = selections.map((selection) => {
|
|
28
|
+
const matches = available.filter((entry) => `${entry.id}@${entry.version}` === selection);
|
|
29
|
+
if (matches.length > 1)
|
|
30
|
+
throw new Error(`Ambiguous authorization extension registration: ${selection}`);
|
|
31
|
+
const extension = matches[0];
|
|
32
|
+
if (!extension)
|
|
33
|
+
throw new Error(`Unknown authorization extension/version: ${selection}`);
|
|
34
|
+
return extension;
|
|
35
|
+
});
|
|
36
|
+
assertUniqueExtensions(resolved);
|
|
37
|
+
return resolved;
|
|
38
|
+
}
|
|
39
|
+
export function readAuthorizationExtensions(environment) {
|
|
40
|
+
const configured = environment.MCP_AUTH_EXTENSIONS?.trim();
|
|
41
|
+
if (!configured)
|
|
42
|
+
return [];
|
|
43
|
+
return resolveAuthorizationExtensions(configured.split(",").map((value) => value.trim()));
|
|
44
|
+
}
|
|
45
|
+
function assertUniqueExtensions(extensions) {
|
|
46
|
+
const ids = new Set();
|
|
47
|
+
for (const extension of extensions) {
|
|
48
|
+
if (!/^[a-z][a-z0-9-]+$/u.test(extension.id)
|
|
49
|
+
|| !/^\d+\.\d+\.\d+$/u.test(extension.version)) {
|
|
50
|
+
throw new Error("Authorization extensions require an ID and an exact integration version");
|
|
51
|
+
}
|
|
52
|
+
if (ids.has(extension.id))
|
|
53
|
+
throw new Error(`Duplicate authorization extension: ${extension.id}`);
|
|
54
|
+
ids.add(extension.id);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/** Union requirements deterministically; a composition can only add requirements. */
|
|
58
|
+
export function validateAuthorizationExtensions(metadata, extensions) {
|
|
59
|
+
assertUniqueExtensions(extensions);
|
|
60
|
+
const requirements = new Map();
|
|
61
|
+
for (const extension of extensions) {
|
|
62
|
+
for (const [field, expected] of Object.entries(extension.requirements)) {
|
|
63
|
+
const existing = requirements.get(field);
|
|
64
|
+
if (existing !== undefined && (existing === true) !== (expected === true)) {
|
|
65
|
+
throw new Error(`Conflicting authorization extension requirements for ${field}`);
|
|
66
|
+
}
|
|
67
|
+
if (expected === true)
|
|
68
|
+
requirements.set(field, true);
|
|
69
|
+
else
|
|
70
|
+
requirements.set(field, new Set([...(existing instanceof Set ? existing : []), ...expected]));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
for (const [field, expected] of [...requirements].sort(([a], [b]) => a.localeCompare(b))) {
|
|
74
|
+
const actual = metadata[field];
|
|
75
|
+
if (expected === true ? actual !== true
|
|
76
|
+
: !Array.isArray(actual) || ![...expected].every((value) => actual.includes(value))) {
|
|
77
|
+
throw new Error(`Authorization Server does not satisfy enabled extension requirement: ${field}`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=auth-extensions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-extensions.js","sourceRoot":"","sources":["../src/auth-extensions.ts"],"names":[],"mappings":"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"}
|
package/dist/auth.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** Public composition surface for hosted resource authorization. */
|
|
2
|
+
export { createResourceAuthorization, type ResourceAuthorizationOptions } from "./authorization.js";
|
|
3
|
+
export { authorizationExtensions, clientCredentialsAuthorization, enterpriseManagedAuthorization, readAuthorizationExtensions, resolveAuthorizationExtensions, validateAuthorizationExtensions, type AuthorizationExtension, } from "./auth-extensions.js";
|
|
4
|
+
export { createJwtTokenVerifier, loadHostedOAuth, type HostedOAuth } from "./oauth.js";
|
package/dist/auth.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** Public composition surface for hosted resource authorization. */
|
|
2
|
+
export { createResourceAuthorization } from "./authorization.js";
|
|
3
|
+
export { authorizationExtensions, clientCredentialsAuthorization, enterpriseManagedAuthorization, readAuthorizationExtensions, resolveAuthorizationExtensions, validateAuthorizationExtensions, } from "./auth-extensions.js";
|
|
4
|
+
export { createJwtTokenVerifier, loadHostedOAuth } from "./oauth.js";
|
|
5
|
+
//# sourceMappingURL=auth.js.map
|
package/dist/auth.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,oEAAoE;AACpE,OAAO,EAAE,2BAA2B,EAAqC,MAAM,oBAAoB,CAAC;AACpG,OAAO,EACL,uBAAuB,EACvB,8BAA8B,EAC9B,8BAA8B,EAC9B,2BAA2B,EAC3B,8BAA8B,EAC9B,+BAA+B,GAEhC,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,sBAAsB,EAAE,eAAe,EAAoB,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type AuthInfo, type OAuthTokenVerifier } from "@modelcontextprotocol/server";
|
|
2
|
+
export interface ResourceAuthorizationOptions {
|
|
3
|
+
readonly verifier: OAuthTokenVerifier;
|
|
4
|
+
readonly resourceMetadataUrl: string;
|
|
5
|
+
readonly requiredScopes: readonly string[];
|
|
6
|
+
/** Explicit implications only; a wildcard-looking string grants nothing by itself. */
|
|
7
|
+
readonly scopeImplications?: Readonly<Record<string, readonly string[]>>;
|
|
8
|
+
}
|
|
9
|
+
/** A hierarchy is an explicit, transitive relation. Cycles terminate and never
|
|
10
|
+
* grant a scope without a verified scope as their starting point.
|
|
11
|
+
*/
|
|
12
|
+
export declare function scopeClosure(granted: readonly string[], implications: ReadonlyMap<string, readonly string[]>): ReadonlySet<string>;
|
|
13
|
+
/** All grants converge on this gate. Extensions never see an unverified token. */
|
|
14
|
+
export declare function createResourceAuthorization(options: ResourceAuthorizationOptions): (request: Request) => Promise<AuthInfo | Response>;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { requireBearerAuth, } from "@modelcontextprotocol/server";
|
|
2
|
+
function validateScopes(scopes) {
|
|
3
|
+
for (const scope of scopes) {
|
|
4
|
+
// RFC 6749 scope-token excludes quotes, backslashes and whitespace.
|
|
5
|
+
if (!/^[\x21\x23-\x5B\x5D-\x7E]+$/u.test(scope) || scope === "offline_access") {
|
|
6
|
+
throw new Error("Resource scopes must be valid OAuth scope tokens and cannot include offline_access");
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
/** A hierarchy is an explicit, transitive relation. Cycles terminate and never
|
|
11
|
+
* grant a scope without a verified scope as their starting point.
|
|
12
|
+
*/
|
|
13
|
+
export function scopeClosure(granted, implications) {
|
|
14
|
+
const result = new Set(granted);
|
|
15
|
+
const pending = [...granted];
|
|
16
|
+
for (let i = 0; i < pending.length; i++) {
|
|
17
|
+
for (const implied of implications.get(pending[i]) ?? []) {
|
|
18
|
+
if (!result.has(implied)) {
|
|
19
|
+
result.add(implied);
|
|
20
|
+
pending.push(implied);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return result;
|
|
25
|
+
}
|
|
26
|
+
/** All grants converge on this gate. Extensions never see an unverified token. */
|
|
27
|
+
export function createResourceAuthorization(options) {
|
|
28
|
+
const requiredScopes = [...new Set(options.requiredScopes)].sort();
|
|
29
|
+
validateScopes(requiredScopes);
|
|
30
|
+
const implications = new Map(Object.entries(options.scopeImplications ?? {})
|
|
31
|
+
.map(([scope, implied]) => {
|
|
32
|
+
validateScopes([scope, ...implied]);
|
|
33
|
+
return [scope, [...implied]];
|
|
34
|
+
}));
|
|
35
|
+
const metadataUrl = new URL(options.resourceMetadataUrl);
|
|
36
|
+
if (metadataUrl.protocol !== "https:" || metadataUrl.username || metadataUrl.password
|
|
37
|
+
|| metadataUrl.search || metadataUrl.hash || /["\\]/u.test(options.resourceMetadataUrl)
|
|
38
|
+
|| Array.from(options.resourceMetadataUrl).some((character) => character.charCodeAt(0) <= 0x20)) {
|
|
39
|
+
throw new Error("Resource metadata must use a safe HTTPS URL");
|
|
40
|
+
}
|
|
41
|
+
const coreGate = requireBearerAuth({
|
|
42
|
+
verifier: options.verifier,
|
|
43
|
+
resourceMetadataUrl: metadataUrl.href,
|
|
44
|
+
});
|
|
45
|
+
const challenge = (status, error) => {
|
|
46
|
+
const parameters = [
|
|
47
|
+
...(error === undefined ? [] : [`error="${error}"`]),
|
|
48
|
+
...(requiredScopes.length === 0 ? [] : [`scope="${requiredScopes.join(" ")}"`]),
|
|
49
|
+
`resource_metadata="${metadataUrl.href}"`,
|
|
50
|
+
];
|
|
51
|
+
return Response.json({ error: error ?? "unauthorized" }, {
|
|
52
|
+
status,
|
|
53
|
+
headers: { "WWW-Authenticate": `Bearer ${parameters.join(", ")}`, "Cache-Control": "no-store" },
|
|
54
|
+
});
|
|
55
|
+
};
|
|
56
|
+
return async (request) => {
|
|
57
|
+
const authorization = request.headers.get("authorization");
|
|
58
|
+
const bearer = authorization === null ? null : /^Bearer +([A-Za-z0-9._~+/-]+=*)$/iu.exec(authorization);
|
|
59
|
+
if (new URL(request.url).searchParams.has("access_token")
|
|
60
|
+
|| (authorization !== null && bearer === null)) {
|
|
61
|
+
return challenge(400, "invalid_request");
|
|
62
|
+
}
|
|
63
|
+
// RFC 6750 permits multiple spaces. The SDK splits on one space; normalize
|
|
64
|
+
// the validated header on a bodyless request so the MCP body remains unread.
|
|
65
|
+
const auth = await coreGate(bearer === null ? request : new Request(request.url, {
|
|
66
|
+
headers: { authorization: `Bearer ${bearer[1]}` },
|
|
67
|
+
}));
|
|
68
|
+
if (auth instanceof Response) {
|
|
69
|
+
// Keep authentication failures distinct from authorization failures and
|
|
70
|
+
// include the complete operation scope set on every challenge.
|
|
71
|
+
if (auth.status === 401)
|
|
72
|
+
return challenge(401, authorization === null ? undefined : "invalid_token");
|
|
73
|
+
return auth;
|
|
74
|
+
}
|
|
75
|
+
const effectiveScopes = scopeClosure(auth.scopes, implications);
|
|
76
|
+
if (!requiredScopes.every((scope) => effectiveScopes.has(scope))) {
|
|
77
|
+
return challenge(403, "insufficient_scope");
|
|
78
|
+
}
|
|
79
|
+
return auth;
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=authorization.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authorization.js","sourceRoot":"","sources":["../src/authorization.ts"],"names":[],"mappings":"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"}
|
package/dist/ci.js
CHANGED
|
@@ -2,7 +2,7 @@ import { CiLogInputSchema, CiLogOutputSchema, compactOutputSchema, } from "./con
|
|
|
2
2
|
import { fetchSessions, fetchSessionTraces } from "./data.js";
|
|
3
3
|
import { runTool } from "./request-scope.js";
|
|
4
4
|
import { telemetryToolResult } from "./telemetry-redaction.js";
|
|
5
|
-
import { READ_ONLY_TELEMETRY_TOOL_ANNOTATIONS } from "./tools.js";
|
|
5
|
+
import { READ_ONLY_TELEMETRY_TOOL_ANNOTATIONS, TELEMETRY_TOOL_AUTH_META } from "./tools.js";
|
|
6
6
|
/** Resource service-name prefix that marks telemetry as CI-emitted. */
|
|
7
7
|
export const CI_SERVICE_PREFIX = "qyl-ci";
|
|
8
8
|
/** CI sessions are the ones that carry at least one qyl-ci service. */
|
|
@@ -78,6 +78,7 @@ export function registerCiTools(server) {
|
|
|
78
78
|
inputSchema: CiLogInputSchema,
|
|
79
79
|
outputSchema: compactOutputSchema(CiLogOutputSchema),
|
|
80
80
|
annotations: READ_ONLY_TELEMETRY_TOOL_ANNOTATIONS,
|
|
81
|
+
_meta: TELEMETRY_TOOL_AUTH_META,
|
|
81
82
|
}, (args, ctx) =>
|
|
82
83
|
// A run breakdown is two units a client can watch: the collector round
|
|
83
84
|
// trip for the run's traces, then the flatten into per-leg phases. The
|
package/dist/ci.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ci.js","sourceRoot":"","sources":["../src/ci.ts"],"names":[],"mappings":"AAmBA,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAC9D,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,oCAAoC,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"ci.js","sourceRoot":"","sources":["../src/ci.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
CHANGED
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
* it through its own environment.
|
|
7
7
|
*/
|
|
8
8
|
/** URI of the trace explorer UI resource. */
|
|
9
|
-
export declare const RESOURCE_URI = "ui://qyl-explorer/mcp-app.html";
|
|
9
|
+
export declare const RESOURCE_URI = "ui://qyl-explorer/mcp-app-v3.html";
|
|
10
10
|
/** URI of the MCP dashboard UI resource. */
|
|
11
|
-
export declare const DASHBOARD_RESOURCE_URI = "ui://qyl-explorer/mcp-dashboard.html";
|
|
11
|
+
export declare const DASHBOARD_RESOURCE_URI = "ui://qyl-explorer/mcp-dashboard-v2.html";
|
|
12
12
|
export declare function collectorUrl(): string;
|
|
13
13
|
/** Optional collector credential and project scope, under the contract's headers. */
|
|
14
14
|
export declare function collectorHeaders(): Record<string, string>;
|
package/dist/config.js
CHANGED
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { API_KEY_HEADER, PROJECT_HEADER } from "./contract-headers.js";
|
|
9
9
|
/** URI of the trace explorer UI resource. */
|
|
10
|
-
export const RESOURCE_URI = "ui://qyl-explorer/mcp-app.html";
|
|
10
|
+
export const RESOURCE_URI = "ui://qyl-explorer/mcp-app-v3.html";
|
|
11
11
|
/** URI of the MCP dashboard UI resource. */
|
|
12
|
-
export const DASHBOARD_RESOURCE_URI = "ui://qyl-explorer/mcp-dashboard.html";
|
|
12
|
+
export const DASHBOARD_RESOURCE_URI = "ui://qyl-explorer/mcp-dashboard-v2.html";
|
|
13
13
|
export function collectorUrl() {
|
|
14
14
|
const configured = process.env.QYL_COLLECTOR_URL ?? "http://127.0.0.1:5100";
|
|
15
15
|
let url;
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvE,6CAA6C;AAC7C,MAAM,CAAC,MAAM,YAAY,GAAG,
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvE,6CAA6C;AAC7C,MAAM,CAAC,MAAM,YAAY,GAAG,mCAAmC,CAAC;AAEhE,4CAA4C;AAC5C,MAAM,CAAC,MAAM,sBAAsB,GAAG,yCAAyC,CAAC;AAEhF,MAAM,UAAU,YAAY;IAC1B,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,uBAAuB,CAAC;IAC5E,IAAI,GAAQ,CAAC;IACb,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;IACvE,CAAC;IACD,IAAI,GAAG,CAAC,QAAQ,KAAK,OAAO,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC1D,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IAC9D,CAAC;IACD,IAAI,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;QAC3D,MAAM,IAAI,KAAK,CACb,kFAAkF,CACnF,CAAC;IACJ,CAAC;IACD,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC;AACxB,CAAC;AAED,qFAAqF;AACrF,MAAM,UAAU,gBAAgB;IAC9B,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC;IAC/C,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC;IAChD,OAAO;QACL,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/C,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,cAAc,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAClD,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Principal } from "./events.js";
|
|
2
|
+
export interface EventsAuthorizationOptions {
|
|
3
|
+
clientId: string;
|
|
4
|
+
clientSecret: string;
|
|
5
|
+
fetch?: typeof fetch;
|
|
6
|
+
now?: () => number;
|
|
7
|
+
}
|
|
8
|
+
export declare function createEventsAuthorization(options: EventsAuthorizationOptions): (principal: Principal) => Promise<boolean>;
|
|
9
|
+
export declare function hostedEventsAuthorization(environment: Readonly<Record<string, string | undefined>>): (principal: Principal) => Promise<boolean>;
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recheck the Auth0 account, explicit application grant, user consent and RBAC
|
|
3
|
+
* permission without retaining the subscriber's OAuth tokens. Management
|
|
4
|
+
* credentials come from the host's secret store; their access token lives only
|
|
5
|
+
* in memory. API failures never authorize delivery.
|
|
6
|
+
*
|
|
7
|
+
* Auth0 Management API: users/{id}, users/{id}/permissions, client-grants, grants.
|
|
8
|
+
*/
|
|
9
|
+
import { z } from "zod";
|
|
10
|
+
import { QYL_MCP_ISSUER, QYL_MCP_RESOURCE, QYL_MCP_SCOPE } from "./oauth.js";
|
|
11
|
+
const REQUEST_TIMEOUT_MS = 10_000;
|
|
12
|
+
const ACCESS_CACHE_MS = 5_000;
|
|
13
|
+
const MAX_CACHE_ENTRIES = 1_000;
|
|
14
|
+
const PAGE_SIZE = 100;
|
|
15
|
+
const MAX_PAGES = 10;
|
|
16
|
+
const TokenSchema = z.object({
|
|
17
|
+
access_token: z.string().min(1),
|
|
18
|
+
token_type: z.literal("Bearer"),
|
|
19
|
+
expires_in: z.number().positive(),
|
|
20
|
+
});
|
|
21
|
+
const UserSchema = z.object({ blocked: z.boolean().optional() });
|
|
22
|
+
const CimdClientSchema = z.object({ client_id: z.string(), external_client_id: z.string().optional() });
|
|
23
|
+
const PermissionSchema = z.object({
|
|
24
|
+
resource_server_identifier: z.string(), permission_name: z.string(),
|
|
25
|
+
});
|
|
26
|
+
const ClientGrantSchema = z.object({
|
|
27
|
+
client_id: z.string().optional(), audience: z.string(),
|
|
28
|
+
subject_type: z.string().optional(), scope: z.array(z.string()),
|
|
29
|
+
});
|
|
30
|
+
const UserGrantSchema = z.object({
|
|
31
|
+
clientID: z.string(), user_id: z.string(), audience: z.string(),
|
|
32
|
+
scope: z.array(z.string()), organization_id: z.string().optional(),
|
|
33
|
+
});
|
|
34
|
+
/** Thrown without response bodies, credentials or subscriber identifiers. */
|
|
35
|
+
class EventsAuthorizationUnavailable extends Error {
|
|
36
|
+
name = "EventsAuthorizationUnavailable";
|
|
37
|
+
constructor() { super("Event authorization is temporarily unavailable"); }
|
|
38
|
+
}
|
|
39
|
+
export function createEventsAuthorization(options) {
|
|
40
|
+
const request = options.fetch ?? fetch;
|
|
41
|
+
const now = options.now ?? Date.now;
|
|
42
|
+
let token;
|
|
43
|
+
let refreshing;
|
|
44
|
+
const pending = new Map();
|
|
45
|
+
const cache = new Map();
|
|
46
|
+
async function managementToken() {
|
|
47
|
+
if (token !== undefined && token.expiresAt > now())
|
|
48
|
+
return token.value;
|
|
49
|
+
refreshing ??= (async () => {
|
|
50
|
+
const response = await request(new URL("oauth/token", QYL_MCP_ISSUER), {
|
|
51
|
+
method: "POST", redirect: "error", signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
|
|
52
|
+
headers: { "content-type": "application/json" },
|
|
53
|
+
body: JSON.stringify({
|
|
54
|
+
grant_type: "client_credentials", client_id: options.clientId,
|
|
55
|
+
client_secret: options.clientSecret, audience: `${QYL_MCP_ISSUER}api/v2/`,
|
|
56
|
+
}),
|
|
57
|
+
});
|
|
58
|
+
if (!response.ok)
|
|
59
|
+
throw new EventsAuthorizationUnavailable();
|
|
60
|
+
const result = TokenSchema.parse(await response.json());
|
|
61
|
+
token = { value: result.access_token, expiresAt: now() + Math.max(0, result.expires_in - 60) * 1_000 };
|
|
62
|
+
return token.value;
|
|
63
|
+
})().finally(() => { refreshing = undefined; });
|
|
64
|
+
return refreshing;
|
|
65
|
+
}
|
|
66
|
+
async function get(path, query = {}) {
|
|
67
|
+
const url = new URL(`api/v2/${path}`, QYL_MCP_ISSUER);
|
|
68
|
+
url.search = new URLSearchParams(query).toString();
|
|
69
|
+
const response = await request(url, {
|
|
70
|
+
redirect: "error", signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
|
|
71
|
+
headers: { authorization: `Bearer ${await managementToken()}` },
|
|
72
|
+
});
|
|
73
|
+
if (response.status === 404)
|
|
74
|
+
return undefined;
|
|
75
|
+
if (!response.ok) {
|
|
76
|
+
if (response.status === 401)
|
|
77
|
+
token = undefined;
|
|
78
|
+
throw new EventsAuthorizationUnavailable();
|
|
79
|
+
}
|
|
80
|
+
return response.json();
|
|
81
|
+
}
|
|
82
|
+
async function any(path, query, schema, predicate) {
|
|
83
|
+
for (let page = 0; page < MAX_PAGES; page++) {
|
|
84
|
+
const body = await get(path, { ...query, per_page: String(PAGE_SIZE), page: String(page) });
|
|
85
|
+
if (body === undefined)
|
|
86
|
+
return false;
|
|
87
|
+
const entries = z.array(schema).parse(body);
|
|
88
|
+
if (entries.some(predicate))
|
|
89
|
+
return true;
|
|
90
|
+
if (entries.length < PAGE_SIZE)
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
// An incomplete permission listing is not evidence of revocation.
|
|
94
|
+
throw new EventsAuthorizationUnavailable();
|
|
95
|
+
}
|
|
96
|
+
async function applicationClientId(clientId) {
|
|
97
|
+
if (!clientId.startsWith("https://"))
|
|
98
|
+
return clientId;
|
|
99
|
+
// Auth0 puts the CIMD URL in the token, but its Management API grants use
|
|
100
|
+
// the internal application ID. Resolve through the trusted issuer only.
|
|
101
|
+
const body = await get("clients", {
|
|
102
|
+
external_client_id: clientId, fields: "client_id,external_client_id",
|
|
103
|
+
include_fields: "true", per_page: "2",
|
|
104
|
+
});
|
|
105
|
+
if (body === undefined)
|
|
106
|
+
return undefined;
|
|
107
|
+
const clients = z.array(CimdClientSchema).parse(body);
|
|
108
|
+
// Auth0's field projection can omit external_client_id. The exact query
|
|
109
|
+
// still filters by it; reject multiple matches or a conflicting value.
|
|
110
|
+
return clients.length === 1
|
|
111
|
+
&& (clients[0].external_client_id === undefined || clients[0].external_client_id === clientId)
|
|
112
|
+
? clients[0].client_id : undefined;
|
|
113
|
+
}
|
|
114
|
+
async function check(principal) {
|
|
115
|
+
const userPath = `users/${encodeURIComponent(principal.subject)}`;
|
|
116
|
+
const body = await get(userPath, { fields: "blocked", include_fields: "true" });
|
|
117
|
+
if (body === undefined || UserSchema.parse(body).blocked === true)
|
|
118
|
+
return false;
|
|
119
|
+
const clientId = await applicationClientId(principal.clientId);
|
|
120
|
+
if (clientId === undefined)
|
|
121
|
+
return false;
|
|
122
|
+
const [permission, application, consent] = await Promise.all([
|
|
123
|
+
any(`${userPath}/permissions`, {}, PermissionSchema, (entry) => entry.resource_server_identifier === QYL_MCP_RESOURCE && entry.permission_name === QYL_MCP_SCOPE),
|
|
124
|
+
any("client-grants", { client_id: clientId, audience: QYL_MCP_RESOURCE, subject_type: "user" }, ClientGrantSchema, (entry) => entry.client_id === clientId && entry.audience === QYL_MCP_RESOURCE
|
|
125
|
+
&& entry.subject_type === "user" && entry.scope.includes(QYL_MCP_SCOPE)),
|
|
126
|
+
any("grants", { user_id: principal.subject, client_id: clientId, audience: QYL_MCP_RESOURCE }, UserGrantSchema, (entry) => entry.user_id === principal.subject && entry.clientID === clientId
|
|
127
|
+
&& entry.audience === QYL_MCP_RESOURCE && entry.organization_id === undefined
|
|
128
|
+
&& entry.scope.includes(QYL_MCP_SCOPE)),
|
|
129
|
+
]);
|
|
130
|
+
return permission && application && consent;
|
|
131
|
+
}
|
|
132
|
+
return (principal) => {
|
|
133
|
+
const key = JSON.stringify([principal.subject, principal.clientId]);
|
|
134
|
+
const cached = cache.get(key);
|
|
135
|
+
if (cached !== undefined && cached.expiresAt > now())
|
|
136
|
+
return Promise.resolve(cached.allowed);
|
|
137
|
+
let checking = pending.get(key);
|
|
138
|
+
if (checking === undefined) {
|
|
139
|
+
checking = check(principal).then((allowed) => {
|
|
140
|
+
if (cache.size >= MAX_CACHE_ENTRIES)
|
|
141
|
+
cache.clear();
|
|
142
|
+
cache.set(key, { allowed, expiresAt: now() + ACCESS_CACHE_MS });
|
|
143
|
+
return allowed;
|
|
144
|
+
}).catch(() => {
|
|
145
|
+
throw new EventsAuthorizationUnavailable();
|
|
146
|
+
}).finally(() => { pending.delete(key); });
|
|
147
|
+
pending.set(key, checking);
|
|
148
|
+
}
|
|
149
|
+
return checking;
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
export function hostedEventsAuthorization(environment) {
|
|
153
|
+
const clientId = environment["MCP_EVENTS_AUTH0_CLIENT_ID"]?.trim();
|
|
154
|
+
const clientSecret = environment["MCP_EVENTS_AUTH0_CLIENT_SECRET"]?.trim();
|
|
155
|
+
if (!clientId || !clientSecret) {
|
|
156
|
+
throw new Error("MCP_EVENTS_STORE requires MCP_EVENTS_AUTH0_CLIENT_ID and MCP_EVENTS_AUTH0_CLIENT_SECRET for ongoing access checks");
|
|
157
|
+
}
|
|
158
|
+
return createEventsAuthorization({ clientId, clientSecret });
|
|
159
|
+
}
|
|
160
|
+
//# sourceMappingURL=events-authorization.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events-authorization.js","sourceRoot":"","sources":["../src/events-authorization.ts"],"names":[],"mappings":"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"}
|