qyl-mcp-server 7.1.0 → 7.2.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.
Files changed (75) hide show
  1. package/README.md +118 -15
  2. package/dist/auth-extensions.d.ts +20 -0
  3. package/dist/auth-extensions.js +81 -0
  4. package/dist/auth-extensions.js.map +1 -0
  5. package/dist/auth.d.ts +4 -0
  6. package/dist/auth.js +5 -0
  7. package/dist/auth.js.map +1 -0
  8. package/dist/authorization.d.ts +14 -0
  9. package/dist/authorization.js +82 -0
  10. package/dist/authorization.js.map +1 -0
  11. package/dist/ci.d.ts +5 -5
  12. package/dist/ci.js +25 -19
  13. package/dist/ci.js.map +1 -1
  14. package/dist/collector-access.d.ts +17 -0
  15. package/dist/collector-access.js +61 -0
  16. package/dist/collector-access.js.map +1 -0
  17. package/dist/collector.d.ts +4 -1
  18. package/dist/collector.js +6 -2
  19. package/dist/collector.js.map +1 -1
  20. package/dist/config.d.ts +4 -3
  21. package/dist/config.js +5 -5
  22. package/dist/config.js.map +1 -1
  23. package/dist/contract-operations.d.ts +1 -1
  24. package/dist/contract-operations.js +1 -1
  25. package/dist/contract-operations.js.map +1 -1
  26. package/dist/contract-validation.d.ts +1 -1
  27. package/dist/contract-validation.js +45 -1
  28. package/dist/contract-validation.js.map +1 -1
  29. package/dist/events-authorization.d.ts +9 -0
  30. package/dist/events-authorization.js +160 -0
  31. package/dist/events-authorization.js.map +1 -0
  32. package/dist/events.d.ts +235 -0
  33. package/dist/events.js +647 -0
  34. package/dist/events.js.map +1 -0
  35. package/dist/main.d.ts +14 -23
  36. package/dist/main.js +99 -36
  37. package/dist/main.js.map +1 -1
  38. package/dist/mcp-app.html +1 -1
  39. package/dist/mcp-dashboard.html +1 -1
  40. package/dist/mcp-home.html +6 -6
  41. package/dist/metrics-tools.js +16 -13
  42. package/dist/metrics-tools.js.map +1 -1
  43. package/dist/native-execution.d.ts +8 -52
  44. package/dist/native-execution.js +51 -222
  45. package/dist/native-execution.js.map +1 -1
  46. package/dist/oauth-metadata.d.ts +8 -0
  47. package/dist/oauth-metadata.js +89 -0
  48. package/dist/oauth-metadata.js.map +1 -0
  49. package/dist/oauth.d.ts +7 -17
  50. package/dist/oauth.js +16 -68
  51. package/dist/oauth.js.map +1 -1
  52. package/dist/request-scope.d.ts +4 -12
  53. package/dist/request-scope.js +9 -22
  54. package/dist/request-scope.js.map +1 -1
  55. package/dist/server.d.ts +7 -1
  56. package/dist/server.js +83 -33
  57. package/dist/server.js.map +1 -1
  58. package/dist/summaries.d.ts +1 -1
  59. package/dist/summaries.js +2 -2
  60. package/dist/summaries.js.map +1 -1
  61. package/dist/telemetry-redaction.js +13 -0
  62. package/dist/telemetry-redaction.js.map +1 -1
  63. package/dist/tools.d.ts +10 -0
  64. package/dist/tools.js +77 -18
  65. package/dist/tools.js.map +1 -1
  66. package/dist/trace-query.d.ts +5 -0
  67. package/dist/trace-query.js +8 -0
  68. package/dist/trace-query.js.map +1 -0
  69. package/dist/ui-domain.d.ts +4 -0
  70. package/dist/ui-domain.js +28 -0
  71. package/dist/ui-domain.js.map +1 -0
  72. package/dist/webhook.d.ts +45 -0
  73. package/dist/webhook.js +198 -0
  74. package/dist/webhook.js.map +1 -0
  75. package/package.json +27 -22
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
- Works with any MCP client. Point it at a collector:
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,17 +24,53 @@ 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 accept only protocol revision `2026-07-28`, on MCP TypeScript SDK 2.0.0 —
28
- Streamable HTTP through `createMcpHandler` and stdio through `serveStdio`, each
29
- with `legacy: "reject"`.
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`,
36
64
  `ci_log`, `display_traces`, `display_mcp_dashboard`.
37
65
 
66
+ `get_trace` returns every span by default. `errors_only` selects error spans;
67
+ `max_spans` (1–1000) caps the result after filtering in Collector order.
68
+ `include_attributes=false` omits span, resource, event, link and instrumentation
69
+ scope attribute collections, including any returned root-span copy. Trace
70
+ totals remain the Collector's totals; the text reports matching and returned
71
+ counts. `ci_log.service_prefix` is case-sensitive, defaults to `qyl-ci`, and
72
+ filters both recent runs and individual phase spans.
73
+
38
74
  **Metrics** — `list_metrics`, `get_metric_series`, `query_metric`. Read in that
39
75
  order: the catalog gives you an exact instrument name and how many attribute
40
76
  streams it has, series discovery tells you which attribute keys are worth
@@ -58,18 +94,20 @@ in-flight collector fetch instead of waiting out its timeout. Progress: a
58
94
  request that carries a `progressToken` gets `notifications/progress` per
59
95
  completed step, one per collector round trip plus a final "Result ready"
60
96
  (`ci_log` with a `run_id` reports the flatten into legs as a step of its own).
61
- Logging: the server declares the `logging` capability and sends one
62
- `notifications/message` per call, `info` on success and `warning` on failure,
63
- under the logger `qyl.mcp`. On revision `2026-07-28` the client's level travels
64
- per request in `_meta["io.modelcontextprotocol/logLevel"]`; a request without
65
- it gets no log line, and `logging/setLevel` does not exist in that revision.
66
- MCP logging is deprecated as of that revision (SEP-2577) and kept here through
67
- the deprecation window beside stderr and OpenTelemetry.
97
+ Logging: the server declares no `logging` capability and sends no
98
+ `notifications/message`, including when a client supplies a log level.
99
+ Operational error diagnostics go to stderr; native tool timing/status telemetry
100
+ uses OpenTelemetry. Requested progress and cancellation remain available.
101
+ [Source and test commands/output, 2026-10-08](https://github.com/ANcpLua/qyl.mcp/blob/main/docs/evidence/2026-10-08-followup-01.md).
102
+
68
103
 
69
104
  Every inbound `tools/call` on a local server — `--stdio`, or HTTP without
70
- `MCP_PUBLIC_URL` — is recorded natively: validated result, lifecycle, duration,
71
- redacted JSON-RPC timeline, and trace/span correlation, persisted atomically to
72
- `~/.qyl/mcp-native-executions.json`. A public deployment (`MCP_PUBLIC_URL` set)
105
+ `MCP_PUBLIC_URL` — records only its tool name, timing, status and error type,
106
+ plus a server-generated execution ID, atomically in
107
+ `~/.qyl/mcp-native-executions.json`. Arguments, request metadata, result bodies
108
+ and error messages are not retained. Known version-1/2 files are reduced to
109
+ this format on load; unreadable files still use the existing archive recovery
110
+ path, and pre-existing archives are not purged. A public deployment (`MCP_PUBLIC_URL` set)
73
111
  records nothing to disk; that evidence file is a local developer artifact, not a
74
112
  multi-tenant audit log.
75
113
 
@@ -80,11 +118,15 @@ multi-tenant audit log.
80
118
  | `QYL_COLLECTOR_URL` | Collector read API base; default `http://127.0.0.1:5100`. Also the OTLP base when set. |
81
119
  | `QYL_API_KEY` | Collector read and OTLP credential. Outgoing only. |
82
120
  | `QYL_PROJECT` | Server-owned collector project scope; defaults to `default`. Never accepted as tool input. |
121
+ | `MCP_COLLECTOR_PROJECTS` | Optional secret JSON mapping validated Auth0 subjects to project-bound Collector keys; see account isolation below. |
83
122
  | `QYL_OTLP_ENDPOINT` | Optional OTLP base for self-telemetry. |
84
123
  | `QYL_DEMO=1` | Explicit, visibly labelled demo telemetry. A collector failure never silently substitutes demo data. |
85
124
  | `QYL_MCP_TELEMETRY=0` | Disable MCP spans, metrics, and operation logs. |
86
- | `QYL_MCP_CAPTURE_CONTENT=1` | Include redacted, size-bounded request and response bodies in operation logs. Off by default. |
125
+ | `QYL_MCP_CAPTURE_CONTENT=1` | Workbench content capture; native incoming tool-call telemetry never supplies request or response bodies. |
87
126
  | `QYL_MCP_NATIVE_STATE_PATH` | Override the native execution-evidence path. |
127
+ | `MCP_EVENTS_STORE` | Persistent Events subscription file; requires Auth0 and the access-check credentials below. |
128
+ | `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. |
129
+ | `MCP_EVENTS_POLL_MS` | Collector polling interval, at least 5000 ms; default 30000 ms. |
88
130
  | `PORT` | HTTP listener port; default `3001`. |
89
131
 
90
132
  Secrets are redacted before results reach the model, structured content, or
@@ -94,8 +136,69 @@ durable evidence.
94
136
  The HTTP entry is a web-standard fetch handler served by its default export,
95
137
  so serving it requires Bun.
96
138
 
139
+ ### Account isolation for hosted Auth0
140
+
141
+ To give a reviewer access to sample data, provision a separate Collector
142
+ project/key through the Collector's `QYL_OTLP_PROJECT_KEYS` configuration and
143
+ assign that key to the reviewer's validated Auth0 subject. Configure the MCP
144
+ service's secret `MCP_COLLECTOR_PROJECTS` with this shape (placeholder values):
145
+
146
+ ```json
147
+ [
148
+ { "project": "default", "apiKey": "OWNER_COLLECTOR_KEY", "subjects": ["auth0|owner-example"] },
149
+ { "project": "review", "apiKey": "REVIEW_COLLECTOR_KEY", "subjects": ["auth0|reviewer-example"] }
150
+ ]
151
+ ```
152
+
153
+ Include every account that should retain access, including the owner. An
154
+ enabled map rejects unmapped callers and never falls back to `QYL_API_KEY`.
155
+ Missing, malformed, duplicate or conflicting entries fail validation. The
156
+ feature requires the hosted Auth0 configuration; local stdio and Cloudflare
157
+ Access deployments cannot enable this map. When the variable is absent, the
158
+ existing deployment-wide credential behavior is retained.
159
+
160
+ Only the verified SDK `AuthInfo.extra.subject` selects the project. Tool inputs
161
+ and request metadata cannot override it. All telemetry tools, viewer refreshes
162
+ and Events queries use that account's project credential. Removing the account
163
+ assignment revokes its Events subscription on the next access check. Project
164
+ keys are redacted from text and structured results, including keys nested in
165
+ this JSON configuration. Keep the map in host secrets and out of the plugin ZIP.
166
+
167
+ `bun run smoke:projects` from the repository root checks all eleven tools,
168
+ viewer query paths, both protocol eras and Events against a real local
169
+ Collector with two temporary projects. Set `QYL_COLLECTOR_PROJECT` to its
170
+ `.csproj` when using a different checkout. The script uses local test identities
171
+ and an in-process signed webhook receiver; the hosted reviewer OAuth login and
172
+ real ChatGPT demonstration are separate checks before upload.
173
+
97
174
  ## Release notes
98
175
 
176
+ ### 7.2.0
177
+
178
+ - Removed deprecated MCP logging capability and per-call log notifications;
179
+ retained requested progress, cancellation and native operation telemetry.
180
+ [Dated verification, 2026-10-08](https://github.com/ANcpLua/qyl.mcp/blob/main/docs/evidence/2026-10-08-followup-01.md).
181
+
182
+ - Optional Auth0-account-to-Collector project isolation, also applied to Events.
183
+ - Events share polling for accounts assigned to the same project; independent
184
+ projects are polled concurrently. Invalid stdio project configuration fails
185
+ before accepting a connection.
186
+ - Workbench telemetry recognizes the SDK's per-request server factory so native
187
+ tool spans are not duplicated by the surrounding protocol journal, while
188
+ failed server construction still produces a correlated failure span.
189
+
190
+ ### 7.1.1
191
+
192
+ - SDK v2.3.1 serving defaults accept modern and 2025-era tool clients over HTTP
193
+ and stdio. The workbench negotiates automatically. The strict policy described
194
+ under 6.0.0 below has been removed.
195
+ - Events recheck account status, explicit client access, user permissions and
196
+ consent through Auth0. Unsubscribe aborts outstanding deliveries; restart
197
+ cleanup removes expired subscriptions and obsolete signing keys.
198
+ - Public viewers declare their deployment origin and keep the requested trace
199
+ limit on refresh. Release verification exercises a fresh npm consumer with
200
+ modern and 2025-era discovery and a real demo-tool call.
201
+
99
202
  ### 7.1.0
100
203
 
101
204
  - 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":"AAcA,MAAM,CAAC,MAAM,8BAA8B,GAA2B;IACpE,EAAE,EAAE,kCAAkC;IACtC,OAAO,EAAE,OAAO;IAChB,SAAS,EAAE,QAAQ;IACnB,aAAa,EAAE,sHAAsH;IACrI,YAAY,EAAE;QACZ,qBAAqB,EAAE,CAAC,6CAA6C,CAAC;QACtE,sCAAsC,EAAE,CAAC,4CAA4C,CAAC;KACvF;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,8BAA8B,GAA2B;IACpE,EAAE,EAAE,0BAA0B;IAC9B,OAAO,EAAE,OAAO;IAChB,SAAS,EAAE,OAAO;IAClB,aAAa,EAAE,6GAA6G;IAC5H,YAAY,EAAE;QACZ,qBAAqB,EAAE,CAAC,oBAAoB,CAAC;QAC7C,qCAAqC,EAAE,CAAC,iBAAiB,CAAC;KAC3D;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,uBAAuB,GAAsC;IACxE,8BAA8B;IAC9B,8BAA8B;CAC/B,CAAC;AAEF,6EAA6E;AAC7E,MAAM,UAAU,8BAA8B,CAC5C,UAA6B,EAC7B,SAAS,GAAsC,uBAAuB;IAEtE,MAAM,QAAQ,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE;QAC5C,MAAM,OAAO,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,KAAK,CAAC,EAAE,IAAI,KAAK,CAAC,OAAO,EAAE,KAAK,SAAS,CAAC,CAAC;QAC1F,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,mDAAmD,SAAS,EAAE,CAAC,CAAC;QACxG,MAAM,SAAS,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QAC7B,IAAI,CAAC,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,4CAA4C,SAAS,EAAE,CAAC,CAAC;QACzF,OAAO,SAAS,CAAC;IACnB,CAAC,CAAC,CAAC;IACH,sBAAsB,CAAC,QAAQ,CAAC,CAAC;IACjC,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,2BAA2B,CACzC,WAAyD;IAEzD,MAAM,UAAU,GAAG,WAAW,CAAC,mBAAmB,EAAE,IAAI,EAAE,CAAC;IAC3D,IAAI,CAAC,UAAU;QAAE,OAAO,EAAE,CAAC;IAC3B,OAAO,8BAA8B,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;AAC5F,CAAC;AAED,SAAS,sBAAsB,CAAC,UAA6C;IAC3E,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAC;IAC9B,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;eACvC,CAAC,kBAAkB,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC;YACjD,MAAM,IAAI,KAAK,CAAC,yEAAyE,CAAC,CAAC;QAC7F,CAAC;QACD,IAAI,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,sCAAsC,SAAS,CAAC,EAAE,EAAE,CAAC,CAAC;QACjG,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IACxB,CAAC;AACH,CAAC;AAED,qFAAqF;AACrF,MAAM,UAAU,+BAA+B,CAC7C,QAAuB,EACvB,UAA6C;IAE7C,sBAAsB,CAAC,UAAU,CAAC,CAAC;IACnC,MAAM,YAAY,GAAG,IAAI,GAAG,EAA8B,CAAC;IAC3D,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,KAAK,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,YAAY,CAAC,EAAE,CAAC;YACvE,MAAM,QAAQ,GAAG,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YACzC,IAAI,QAAQ,KAAK,SAAS,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC,KAAK,CAAC,QAAQ,KAAK,IAAI,CAAC,EAAE,CAAC;gBAC1E,MAAM,IAAI,KAAK,CAAC,wDAAwD,KAAK,EAAE,CAAC,CAAC;YACnF,CAAC;YACD,IAAI,QAAQ,KAAK,IAAI;gBAAE,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;;gBAChD,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,QAAQ,YAAY,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;QACrG,CAAC;IACH,CAAC;IACD,KAAK,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACzF,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;QAC/B,IAAI,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,KAAK,IAAI;YACrC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;YACtF,MAAM,IAAI,KAAK,CAAC,wEAAwE,KAAK,EAAE,CAAC,CAAC;QACnG,CAAC;IACH,CAAC;AACH,CAAC"}
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
@@ -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.d.ts CHANGED
@@ -15,11 +15,11 @@ import type { McpServer } from "@modelcontextprotocol/server";
15
15
  import type { Mode, QylSession, QylTrace } from "./wire.js";
16
16
  /** Resource service-name prefix that marks telemetry as CI-emitted. */
17
17
  export declare const CI_SERVICE_PREFIX = "qyl-ci";
18
- /** CI sessions are the ones that carry at least one qyl-ci service. */
19
- export declare function filterCiSessions(sessions: QylSession[]): QylSession[];
18
+ /** CI sessions carry at least one service matching the requested prefix. */
19
+ export declare function filterCiSessions(sessions: QylSession[], servicePrefix?: string): QylSession[];
20
20
  /** Flatten a run's traces into per-leg phases, failures first. */
21
- export declare function collectCiPhases(traces: QylTrace[]): CiPhase[];
22
- export declare function summarizeCiRuns(runs: CiRunSummary[], mode: Mode): string;
23
- export declare function summarizeCiRun(runId: string, phases: CiPhase[], mode: Mode): string;
21
+ export declare function collectCiPhases(traces: QylTrace[], servicePrefix?: string): CiPhase[];
22
+ export declare function summarizeCiRuns(runs: CiRunSummary[], mode: Mode, servicePrefix?: string): string;
23
+ export declare function summarizeCiRun(runId: string, phases: CiPhase[], mode: Mode, servicePrefix?: string): string;
24
24
  /** Register the CI dogfooding block. */
25
25
  export declare function registerCiTools(server: McpServer): void;
package/dist/ci.js CHANGED
@@ -2,12 +2,12 @@ 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
- /** CI sessions are the ones that carry at least one qyl-ci service. */
9
- export function filterCiSessions(sessions) {
10
- return sessions.filter((session) => session.services.some((service) => service.startsWith(CI_SERVICE_PREFIX)));
8
+ /** CI sessions carry at least one service matching the requested prefix. */
9
+ export function filterCiSessions(sessions, servicePrefix = CI_SERVICE_PREFIX) {
10
+ return sessions.filter((session) => session.services.some((service) => service.startsWith(servicePrefix)));
11
11
  }
12
12
  function spanLeg(span) {
13
13
  const attribute = span.attributes?.find((entry) => entry.key === "ci.leg");
@@ -16,8 +16,8 @@ function spanLeg(span) {
16
16
  : span.resource.service_name;
17
17
  }
18
18
  /** Flatten a run's traces into per-leg phases, failures first. */
19
- export function collectCiPhases(traces) {
20
- const phases = traces.flatMap((trace) => trace.spans.map((span) => ({
19
+ export function collectCiPhases(traces, servicePrefix = CI_SERVICE_PREFIX) {
20
+ const phases = traces.flatMap((trace) => trace.spans.filter((span) => span.resource.service_name.startsWith(servicePrefix)).map((span) => ({
21
21
  leg: spanLeg(span),
22
22
  phase: span.name,
23
23
  status: span.status.code === 2 ? "error" : span.status.code === 1 ? "ok" : "unset",
@@ -32,10 +32,10 @@ export function collectCiPhases(traces) {
32
32
  ? 1
33
33
  : 0);
34
34
  }
35
- export function summarizeCiRuns(runs, mode) {
35
+ export function summarizeCiRuns(runs, mode, servicePrefix = CI_SERVICE_PREFIX) {
36
36
  if (runs.length === 0) {
37
37
  return `No CI runs found (${mode} mode). CI telemetry appears once runs emit ` +
38
- `spans with a '${CI_SERVICE_PREFIX}*' service.name.`;
38
+ `spans with a '${servicePrefix}*' service.name.`;
39
39
  }
40
40
  const lines = runs.map((run) => {
41
41
  const failure = run.error_count > 0 ? `${run.error_count} error(s)` : "clean";
@@ -44,9 +44,9 @@ export function summarizeCiRuns(runs, mode) {
44
44
  });
45
45
  return `${runs.length} CI run(s) (${mode} mode), pass a run_id for the per-leg breakdown:\n${lines.join("\n")}`;
46
46
  }
47
- export function summarizeCiRun(runId, phases, mode) {
47
+ export function summarizeCiRun(runId, phases, mode, servicePrefix = CI_SERVICE_PREFIX) {
48
48
  if (phases.length === 0) {
49
- return `CI run ${runId} has no phase spans (${mode} mode).`;
49
+ return `CI run ${runId} has no phase spans matching '${servicePrefix}*' (${mode} mode).`;
50
50
  }
51
51
  const legs = new Map();
52
52
  for (const phase of phases) {
@@ -71,29 +71,35 @@ export function summarizeCiRun(runId, phases, mode) {
71
71
  export function registerCiTools(server) {
72
72
  server.registerTool("ci_log", {
73
73
  title: "CI Log",
74
- description: "Read qyl's own CI runs from its telemetry (dogfooding — no GitHub API). " +
75
- "Without arguments: recent CI runs (sessions whose service.name starts with " +
76
- `'${CI_SERVICE_PREFIX}'). With run_id: per-leg phase breakdown, failures first, ` +
77
- "so 'which leg hung on what' is answerable even when GitHub's log API is down.",
74
+ description: "Read CI telemetry from qyl when the user wants recent runs or a per-leg " +
75
+ "phase breakdown with failures first. Any CI can emit this convention: " +
76
+ `resource service.name starts with service_prefix (default '${CI_SERVICE_PREFIX}'), session.id identifies ` +
77
+ "the run, and one span per phase carries a ci.leg attribute; failed phases " +
78
+ "set span status to error. Without run_id, filters the 50 most recent " +
79
+ "sessions and returns up to limit matching runs (default 10). With run_id, " +
80
+ "reads up to 100 traces for that session and returns only phases matching " +
81
+ "the same case-sensitive service prefix; phase output can be large.",
78
82
  inputSchema: CiLogInputSchema,
79
83
  outputSchema: compactOutputSchema(CiLogOutputSchema),
80
84
  annotations: READ_ONLY_TELEMETRY_TOOL_ANNOTATIONS,
85
+ _meta: TELEMETRY_TOOL_AUTH_META,
81
86
  }, (args, ctx) =>
82
87
  // A run breakdown is two units a client can watch: the collector round
83
88
  // trip for the run's traces, then the flatten into per-leg phases. The
84
89
  // run list is one round trip.
85
- runTool(ctx, "ci_log", args.run_id ? 2 : 1, async (scope) => {
90
+ runTool(ctx, args.run_id ? 2 : 1, async (scope) => {
91
+ const servicePrefix = args.service_prefix ?? CI_SERVICE_PREFIX;
86
92
  if (args.run_id) {
87
93
  const { traces, mode } = await fetchSessionTraces(args.run_id, 100, scope.collector);
88
94
  await scope.step(`Fetched ${traces.length} trace(s) of CI run ${args.run_id}`);
89
- const phases = collectCiPhases(traces);
95
+ const phases = collectCiPhases(traces, servicePrefix);
90
96
  const legs = new Set(phases.map((phase) => phase.leg)).size;
91
97
  await scope.step(`Collected ${phases.length} phase(s) across ${legs} leg(s)`);
92
98
  const output = { run_id: args.run_id, phases, mode };
93
- return telemetryToolResult(summarizeCiRun(args.run_id, phases, mode), output);
99
+ return telemetryToolResult(summarizeCiRun(args.run_id, phases, mode, servicePrefix), output);
94
100
  }
95
101
  const { sessions, mode } = await fetchSessions(50, undefined, scope.collector);
96
- const runs = filterCiSessions(sessions)
102
+ const runs = filterCiSessions(sessions, servicePrefix)
97
103
  .slice(0, args.limit ?? 10)
98
104
  .map((session) => ({
99
105
  run_id: session["session_id"],
@@ -105,7 +111,7 @@ export function registerCiTools(server) {
105
111
  }));
106
112
  await scope.step(`Found ${runs.length} CI run(s) among ${sessions.length} session(s)`);
107
113
  const output = { runs, mode };
108
- return telemetryToolResult(summarizeCiRuns(runs, mode), output);
114
+ return telemetryToolResult(summarizeCiRuns(runs, mode, servicePrefix), output);
109
115
  }));
110
116
  }
111
117
  //# sourceMappingURL=ci.js.map
package/dist/ci.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ci.js","sourceRoot":"","sources":["../src/ci.ts"],"names":[],"mappings":"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"}
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,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAG5F,uEAAuE;AACvE,MAAM,CAAC,MAAM,iBAAiB,GAAG,QAAQ,CAAC;AAE1C,4EAA4E;AAC5E,MAAM,UAAU,gBAAgB,CAC9B,QAAsB,EACtB,aAAa,GAAG,iBAAiB;IAEjC,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CACjC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC,CACtE,CAAC;AACJ,CAAC;AAED,SAAS,OAAO,CAAC,IAAa;IAC5B,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC;IAC3E,OAAO,OAAO,SAAS,EAAE,KAAK,KAAK,QAAQ;QACzC,CAAC,CAAC,SAAS,CAAC,KAAK;QACjB,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC;AACjC,CAAC;AAED,kEAAkE;AAClE,MAAM,UAAU,eAAe,CAAC,MAAkB,EAAE,aAAa,GAAG,iBAAiB;IACnF,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CACtC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAW,EAAE,CAAC,CAAC;QACzG,GAAG,EAAE,OAAO,CAAC,IAAI,CAAC;QAClB,KAAK,EAAE,IAAI,CAAC,IAAI;QAChB,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO;QAClF,WAAW,EAAE,IAAI,CAAC,GAAG,CACnB,CAAC,EACD,IAAI,CAAC,KAAK,CACR,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,kBAAkB,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC,GAAG,SAAS,CACxF,CACF;QACD,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACjE,CAAC,CAAC,CACJ,CAAC;IACF,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAC1B,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM;QACnB,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC;QAC9D,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,OAAO;YACpB,CAAC,CAAC,CAAC,CAAC;YACJ,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,OAAO;gBACpB,CAAC,CAAC,CAAC;gBACH,CAAC,CAAC,CAAC,CACV,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAoB,EAAE,IAAU,EAAE,aAAa,GAAG,iBAAiB;IACjG,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,OAAO,qBAAqB,IAAI,8CAA8C;YAC5E,iBAAiB,aAAa,kBAAkB,CAAC;IACrD,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;QAC7B,MAAM,OAAO,GAAG,GAAG,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,WAAW,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC;QAC9E,MAAM,QAAQ,GAAG,GAAG,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC;QAChG,OAAO,KAAK,GAAG,CAAC,MAAM,KAAK,GAAG,CAAC,KAAK,KAAK,GAAG,CAAC,UAAU,IAAI,QAAQ,MAAM,OAAO,EAAE,CAAC;IACrF,CAAC,CAAC,CAAC;IACH,OAAO,GAAG,IAAI,CAAC,MAAM,eAAe,IAAI,qDAAqD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AAClH,CAAC;AAED,MAAM,UAAU,cAAc,CAC5B,KAAa,EACb,MAAiB,EACjB,IAAU,EACV,aAAa,GAAG,iBAAiB;IAEjC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,UAAU,KAAK,iCAAiC,aAAa,OAAO,IAAI,SAAS,CAAC;IAC3F,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAqB,CAAC;IAC1C,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACrC,IAAI,QAAQ;YAAE,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;;YAC9B,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IACpC,CAAC;IACD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,CAAC,GAAG,EAAE,SAAS,CAAC,IAAI,IAAI,EAAE,CAAC;QACpC,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,OAAO,CAAC,CAAC;QACrE,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,EAAE,CAAC,CAAC;QACtD,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC;YAC3D,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC1D,KAAK,CAAC,IAAI,CAAC,OAAO,KAAK,CAAC,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,CAAC,KAAK,KAAK,KAAK,CAAC,WAAW,MAAM,MAAM,EAAE,CAAC,CAAC;QAC7G,CAAC;IACH,CAAC;IACD,OAAO,UAAU,KAAK,KAAK,IAAI,YAAY,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AAChE,CAAC;AAED,wCAAwC;AACxC,MAAM,UAAU,eAAe,CAAC,MAAiB;IAC/C,MAAM,CAAC,YAAY,CACjB,QAAQ,EACR;QACE,KAAK,EAAE,QAAQ;QACf,WAAW,EACT,0EAA0E;YAC1E,wEAAwE;YACxE,8DAA8D,iBAAiB,4BAA4B;YAC3G,4EAA4E;YAC5E,uEAAuE;YACvE,4EAA4E;YAC5E,2EAA2E;YAC3E,oEAAoE;QACtE,WAAW,EAAE,gBAAgB;QAC7B,YAAY,EAAE,mBAAmB,CAAC,iBAAiB,CAAC;QACpD,WAAW,EAAE,oCAAoC;QACjD,KAAK,EAAE,wBAAwB;KAChC,EACD,CAAC,IAAgB,EAAE,GAAkB,EAA2B,EAAE;IAChE,uEAAuE;IACvE,uEAAuE;IACvE,8BAA8B;IAC9B,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;QAChD,MAAM,aAAa,GAAG,IAAI,CAAC,cAAc,IAAI,iBAAiB,CAAC;QAC/D,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,kBAAkB,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;YACrF,MAAM,KAAK,CAAC,IAAI,CAAC,WAAW,MAAM,CAAC,MAAM,uBAAuB,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;YAC/E,MAAM,MAAM,GAAG,eAAe,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;YACtD,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;YAC5D,MAAM,KAAK,CAAC,IAAI,CAAC,aAAa,MAAM,CAAC,MAAM,oBAAoB,IAAI,SAAS,CAAC,CAAC;YAC9E,MAAM,MAAM,GAAgB,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;YAClE,OAAO,mBAAmB,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,CAAC,EAAE,MAAM,CAAC,CAAC;QAC/F,CAAC;QACD,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,MAAM,aAAa,CAAC,EAAE,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;QAC/E,MAAM,IAAI,GAAG,gBAAgB,CAAC,QAAQ,EAAE,aAAa,CAAC;aACnD,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;aAC1B,GAAG,CAAC,CAAC,OAAO,EAAgB,EAAE,CAAC,CAAC;YAC/B,MAAM,EAAE,OAAO,CAAC,YAAY,CAAC;YAC7B,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,GAAG,CAAC,OAAO,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC;YAClF,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,QAAQ,EAAE,OAAO,CAAC,QAAQ;SAC3B,CAAC,CAAC,CAAC;QACN,MAAM,KAAK,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,MAAM,oBAAoB,QAAQ,CAAC,MAAM,aAAa,CAAC,CAAC;QACvF,MAAM,MAAM,GAAgB,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QAC3C,OAAO,mBAAmB,CAAC,eAAe,CAAC,IAAI,EAAE,IAAI,EAAE,aAAa,CAAC,EAAE,MAAM,CAAC,CAAC;IACjF,CAAC,CAAC,CACL,CAAC;AACJ,CAAC"}
@@ -0,0 +1,17 @@
1
+ /** A project-bound Collector credential, supplied only by host configuration. */
2
+ export interface CollectorAccess {
3
+ readonly project: string;
4
+ readonly apiKey: string;
5
+ }
6
+ /** Safe to return to a caller; never includes subjects, projects or credentials. */
7
+ export declare class CollectorAccessError extends Error {
8
+ constructor();
9
+ }
10
+ /**
11
+ * Opt-in subject-to-project access. Absence retains the single-project setup;
12
+ * present-but-invalid configuration and unassigned callers never fall back.
13
+ * Values stay in the host's secret configuration, not in tool arguments.
14
+ */
15
+ export declare function readCollectorProjects(environment?: Readonly<Record<string, string | undefined>>): ReadonlyMap<string, CollectorAccess> | undefined;
16
+ /** Pass only the subject from verified SDK AuthInfo, never request metadata. */
17
+ export declare function collectorAccessForSubject(subject: unknown, environment?: Readonly<Record<string, string | undefined>>): CollectorAccess | undefined;