qyl-mcp-server 7.0.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 +60 -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/cloudflare-access.d.ts +16 -0
- package/dist/cloudflare-access.js +75 -0
- package/dist/cloudflare-access.js.map +1 -0
- 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 +15 -28
- package/dist/main.js +93 -40
- 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/secret-redactor.js +2 -1
- package/dist/secret-redactor.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,31 @@ 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
|
+
|
|
142
|
+
### 7.1.0
|
|
143
|
+
|
|
144
|
+
- The hosted server can sit behind Cloudflare Access Managed OAuth:
|
|
145
|
+
`MCP_AUTH_PROVIDER=cloudflare-access` with `MCP_ACCESS_TEAM_DOMAIN` and
|
|
146
|
+
`MCP_ACCESS_AUD`. Access performs the client OAuth flow and owns discovery;
|
|
147
|
+
the origin serves `/mcp` only for a `Cf-Access-Jwt-Assertion` it has verified
|
|
148
|
+
against the team's signing keys for RS256, issuer, application audience,
|
|
149
|
+
expiry and subject, so a direct request to the origin without one is
|
|
150
|
+
rejected. The default stays the pinned Auth0 issuer; unknown modes, partial
|
|
151
|
+
Access settings and non-Cloudflare team URLs fail closed.
|
|
152
|
+
- The assertion header is redacted from diagnostic objects and text, like the
|
|
153
|
+
other credentials.
|
|
154
|
+
|
|
99
155
|
### 7.0.0
|
|
100
156
|
|
|
101
157
|
- Contract `@ancplua/qyl-api-schema` 11.1.0 -> 11.2.0. Demo series ids are
|
|
@@ -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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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type JWTVerifyGetKey } from "jose";
|
|
2
|
+
import type { HostedAuth } from "./main.js";
|
|
3
|
+
export interface AccessConfig {
|
|
4
|
+
teamDomain: string;
|
|
5
|
+
audience: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function readAccessConfig(environment: Readonly<Record<string, string | undefined>>): AccessConfig | undefined;
|
|
8
|
+
/** Access validates the client's opaque OAuth token at the edge. The origin
|
|
9
|
+
* accepts only its signed assertion, including on the direct Railway hostname.
|
|
10
|
+
* Membership of this Access app authorizes the server's read-only tool surface;
|
|
11
|
+
* the assertion does not carry an OAuth client ID or qyl scopes.
|
|
12
|
+
*/
|
|
13
|
+
export declare function createCloudflareAccessAuth(params: AccessConfig & {
|
|
14
|
+
resource: URL;
|
|
15
|
+
key?: JWTVerifyGetKey;
|
|
16
|
+
}): HostedAuth;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { createRemoteJWKSet, jwtVerify } from "jose";
|
|
2
|
+
import { QYL_MCP_SCOPE } from "./oauth.js";
|
|
3
|
+
function validateConfig(config) {
|
|
4
|
+
const team = new URL(config.teamDomain);
|
|
5
|
+
if (team.protocol !== "https:" || !/^[a-z0-9-]+\.cloudflareaccess\.com$/u.test(team.hostname)
|
|
6
|
+
|| team.port || team.username || team.password || team.pathname !== "/" || team.search || team.hash) {
|
|
7
|
+
throw new Error("MCP_ACCESS_TEAM_DOMAIN must be an HTTPS Cloudflare Access team origin");
|
|
8
|
+
}
|
|
9
|
+
if (!config.audience.trim() || config.audience !== config.audience.trim()) {
|
|
10
|
+
throw new Error("MCP_ACCESS_AUD must be the Access application's audience tag");
|
|
11
|
+
}
|
|
12
|
+
return { teamDomain: team.origin, audience: config.audience };
|
|
13
|
+
}
|
|
14
|
+
export function readAccessConfig(environment) {
|
|
15
|
+
const provider = environment.MCP_AUTH_PROVIDER?.trim() || "auth0";
|
|
16
|
+
if (provider === "auth0") {
|
|
17
|
+
if (environment.MCP_ACCESS_TEAM_DOMAIN || environment.MCP_ACCESS_AUD) {
|
|
18
|
+
throw new Error("Set MCP_AUTH_PROVIDER=cloudflare-access when configuring an Access application");
|
|
19
|
+
}
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
if (provider !== "cloudflare-access")
|
|
23
|
+
throw new Error("MCP_AUTH_PROVIDER must be auth0 or cloudflare-access");
|
|
24
|
+
if (!environment.MCP_ACCESS_TEAM_DOMAIN || !environment.MCP_ACCESS_AUD) {
|
|
25
|
+
throw new Error("Cloudflare Access requires MCP_ACCESS_TEAM_DOMAIN and MCP_ACCESS_AUD");
|
|
26
|
+
}
|
|
27
|
+
return validateConfig({ teamDomain: environment.MCP_ACCESS_TEAM_DOMAIN, audience: environment.MCP_ACCESS_AUD });
|
|
28
|
+
}
|
|
29
|
+
/** Access validates the client's opaque OAuth token at the edge. The origin
|
|
30
|
+
* accepts only its signed assertion, including on the direct Railway hostname.
|
|
31
|
+
* Membership of this Access app authorizes the server's read-only tool surface;
|
|
32
|
+
* the assertion does not carry an OAuth client ID or qyl scopes.
|
|
33
|
+
*/
|
|
34
|
+
export function createCloudflareAccessAuth(params) {
|
|
35
|
+
const { teamDomain, audience } = validateConfig(params);
|
|
36
|
+
const key = params.key ?? createRemoteJWKSet(new URL("/cdn-cgi/access/certs", teamDomain));
|
|
37
|
+
const metadataUrl = new URL("/.well-known/oauth-protected-resource", params.resource).href;
|
|
38
|
+
function unauthorized() {
|
|
39
|
+
return Response.json({ error: "invalid_token", error_description: "Cloudflare Access authentication required" }, {
|
|
40
|
+
status: 401,
|
|
41
|
+
headers: {
|
|
42
|
+
"cache-control": "no-store",
|
|
43
|
+
"www-authenticate": `Bearer resource_metadata="${metadataUrl}"`,
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
async gate(request) {
|
|
49
|
+
const assertion = request.headers.get("cf-access-jwt-assertion");
|
|
50
|
+
if (!assertion || assertion.length > 16_384)
|
|
51
|
+
return unauthorized();
|
|
52
|
+
try {
|
|
53
|
+
const { payload } = await jwtVerify(assertion, key, {
|
|
54
|
+
issuer: teamDomain, audience, algorithms: ["RS256"], requiredClaims: ["exp", "sub"],
|
|
55
|
+
});
|
|
56
|
+
if (typeof payload.sub !== "string" || !payload.sub || typeof payload.exp !== "number")
|
|
57
|
+
return unauthorized();
|
|
58
|
+
return {
|
|
59
|
+
token: assertion,
|
|
60
|
+
clientId: "cloudflare-access",
|
|
61
|
+
scopes: [QYL_MCP_SCOPE],
|
|
62
|
+
expiresAt: payload.exp,
|
|
63
|
+
resource: params.resource,
|
|
64
|
+
extra: { subject: payload.sub, provider: "cloudflare-access" },
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
return unauthorized();
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
// Access owns discovery and authorization challenges in this mode. Serving
|
|
72
|
+
// the Auth0 metadata here would send clients through the wrong OAuth flow.
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=cloudflare-access.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cloudflare-access.js","sourceRoot":"","sources":["../src/cloudflare-access.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>;
|