@mgcrea/mcp-loki 0.0.0 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Olivier Louvignes
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,91 @@
1
1
  # @mgcrea/mcp-loki
2
2
 
3
- Placeholder. See https://github.com/mgcrea/mcp-loki
3
+ A [Model Context Protocol](https://modelcontextprotocol.io) server for the
4
+ [Grafana Loki](https://grafana.com/oss/loki/) HTTP API: query logs and LogQL metrics, explore
5
+ labels, fields, volume and patterns, with answers shaped to fit a context window.
6
+
7
+ The server is **read-only**. It sends only reads: Loki's push, delete-request and ruler-write
8
+ endpoints are not wrapped, and the `loki_request` escape hatch only sends GET.
9
+
10
+ ## Features
11
+
12
+ - **Logs merged across streams, in time order.** Labels every stream shares come once as
13
+ `common_labels`. Each line keeps only the labels that tell its stream apart, plus `level` and
14
+ structured metadata. Timestamps are exact RFC3339 nanoseconds, so the `next` cursor and
15
+ `loki_get_log_context` anchors round-trip without loss.
16
+ - **Cheap before expensive.** `loki_get_stats` and `loki_get_volume` answer from the index
17
+ without reading a line. `loki_list_patterns` summarizes what a service logs as templates.
18
+ `loki_query_metric` counts and ranks without returning lines.
19
+ - **Long lines are cut** at `max_line_chars` (some services log 300 KB lines), ANSI colour
20
+ codes are stripped, and the Kubernetes `filename` label is hidden by default.
21
+ - **Errors carry a remedy.** Loki answers a rejected query with plain text. The common ones
22
+ (empty-compatible matchers, parse errors, range and series limits, timeouts) come back with
23
+ what to change.
24
+ - **Identity and limits up front.** `loki_auth_status` names the tenant, the version,
25
+ retention, max query length, max lines and series per query, and whether volume and patterns
26
+ are enabled. Every data answer carries `tenant`.
27
+
28
+ ## Configure
29
+
30
+ | Variable | Required | Description |
31
+ | ------------------ | -------- | -------------------------------------------------------------------------------------------------------------------------------- |
32
+ | `LOKI_URL` | yes | Loki base URL (gateway, query-frontend or single binary), with any path prefix. |
33
+ | `LOKI_USERNAME` | no | Basic auth. Behind the Loki Helm chart's nginx gateway the username **is the tenant**. |
34
+ | `LOKI_PASSWORD` | no | Basic auth password. |
35
+ | `LOKI_TOKEN` | no | Bearer token instead of basic auth (Grafana Cloud, an OAuth proxy). |
36
+ | `LOKI_TENANT_ID` | no | Sent as `X-Scope-OrgID`, for a multi-tenant Loki reached directly. A gateway that maps the basic-auth username overrides it. |
37
+ | `LOKI_HEADERS` | no | Extra headers as a JSON object. |
38
+ | `LOKI_TIMEOUT` | no | HTTP timeout per request, seconds (default 60). |
39
+ | `LOKI_MAX_RETRIES` | no | Retries for 429 and proxy 502/503 (default 2). A 504 is never retried: on Loki it is a slow query, and a retry triples the load. |
40
+
41
+ With nothing configured the server still starts and serves `loki_auth_status`, which says what
42
+ to set.
43
+
44
+ ## Quick start
45
+
46
+ ```bash
47
+ pnpm install
48
+ pnpm build
49
+ ```
50
+
51
+ Then copy `.mcp.json.example` to `.mcp.json` and fill it in.
52
+
53
+ ## Tools
54
+
55
+ | Tool | What it does |
56
+ | --------------------------- | ---------------------------------------------------------------------------------- |
57
+ | `loki_auth_status` | URL, auth, tenant, version and this tenant's limits; setup steps when unconfigured |
58
+ | `loki_query_logs` | LogQL log query over a range, lines merged across streams, with a `next` cursor |
59
+ | `loki_get_log_context` | The lines just before and after one line, in its own stream |
60
+ | `loki_query_metric` | LogQL metric query at an instant, ranked largest first |
61
+ | `loki_query_metric_range` | LogQL metric query over a range, on a step grid, with per-series stats |
62
+ | `loki_list_labels` | Stream labels with their cardinality |
63
+ | `loki_list_label_values` | Values of one label, optionally within a selector |
64
+ | `loki_list_series` | Streams matching a selector |
65
+ | `loki_list_detected_fields` | JSON / logfmt / structured-metadata fields in the lines, or one field's values |
66
+ | `loki_get_volume` | Bytes per namespace / app / stream from the index, largest first |
67
+ | `loki_get_stats` | Streams, chunks, lines and bytes a selector covers, from the index |
68
+ | `loki_list_patterns` | Line templates with counts, from the pattern ingester |
69
+ | `loki_list_rules` | The Loki ruler's alerting and recording rules |
70
+ | `loki_request` | GET any other read endpoint (`/loki/api/v1/*`, `/prometheus/api/v1/*`, `/config`) |
71
+
72
+ ## Develop
73
+
74
+ ```bash
75
+ pnpm dev # tsdown --watch
76
+ pnpm test # vitest
77
+ pnpm typecheck
78
+ pnpm lint
79
+ pnpm format
80
+ ```
81
+
82
+ ### Publish
83
+
84
+ ```bash
85
+ pnpm dlx release-it # bump, commit, tag
86
+ git push --follow-tags # CI publishes to npm from the tag
87
+ ```
88
+
89
+ ## License
90
+
91
+ MIT
package/dist/cli.d.ts ADDED
@@ -0,0 +1 @@
1
+ export {}
package/dist/cli.js ADDED
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env node
2
+ import { _ as BUILD_INFO, f as authMode, g as setupInstructions, i as createServer, m as loadConfig, p as isConfigured, s as describeError } from "./server-B2TOeJ3P.js";
3
+ import { ZodError } from "zod";
4
+ import { StdioServerTransport } from "@modelcontextprotocol/server/stdio";
5
+ // src/cli.ts
6
+ const stderrLogger = {
7
+ debug: (...args) => {
8
+ if (process.env.LOKI_DEBUG) console.error("[loki-mcp]", ...args);
9
+ },
10
+ warn: (...args) => console.error("[loki-mcp]", ...args),
11
+ error: (...args) => console.error("[loki-mcp]", ...args)
12
+ };
13
+ /** Show a config mistake as its field messages, not 40 frames of zod internals. */
14
+ const describeFatal = (err) => {
15
+ if (err instanceof ZodError) return err.issues.map((issue) => {
16
+ const path = issue.path.join(".");
17
+ return path ? `${path}: ${issue.message}` : issue.message;
18
+ }).join("\n");
19
+ return err instanceof Error ? err.message : String(err);
20
+ };
21
+ const main = async () => {
22
+ stderrLogger.warn(`${BUILD_INFO.name}@${BUILD_INFO.version} (git ${BUILD_INFO.gitCommit} ${BUILD_INFO.gitCommitDate}, node ${process.version})`);
23
+ const config = loadConfig();
24
+ const { server, ctx } = createServer({
25
+ config,
26
+ logger: stderrLogger
27
+ });
28
+ const transport = new StdioServerTransport();
29
+ await server.connect(transport);
30
+ stderrLogger.warn(`loki-mcp connected (url=${config.url ?? "MISSING"}, auth=${authMode(config)}, tenant=${ctx.tenant?.tenant ?? "none"}, read-only)`);
31
+ for (const line of setupInstructions(config)) stderrLogger.warn(line);
32
+ if (isConfigured(config)) ctx.identity().then((id) => {
33
+ const l = id.limits ?? {};
34
+ stderrLogger.warn(`loki ${id.version ?? "?"} at ${new URL(config.url).host}` + (ctx.tenant ? `, tenant ${ctx.tenant.tenant}` : "") + (l.retention ? `, retention ${l.retention}` : "") + (l.maxQueryLength ? `, max range ${l.maxQueryLength}` : ""));
35
+ }).catch((err) => {
36
+ const { error, remedy } = describeError(err);
37
+ stderrLogger.warn(`loki unreachable: ${error}${remedy ? ` — ${String(remedy)}` : ""}`);
38
+ });
39
+ const shutdown = (signal) => {
40
+ stderrLogger.warn(`received ${signal}, shutting down`);
41
+ process.exit(0);
42
+ };
43
+ process.on("SIGINT", () => shutdown("SIGINT"));
44
+ process.on("SIGTERM", () => shutdown("SIGTERM"));
45
+ };
46
+ main().catch((err) => {
47
+ console.error(`[loki-mcp] fatal: ${describeFatal(err)}`);
48
+ process.exit(1);
49
+ });
50
+ export {};
51
+
52
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","names":[],"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { StdioServerTransport } from \"@modelcontextprotocol/server/stdio\";\nimport { ZodError } from \"zod\";\n\nimport { BUILD_INFO } from \"#/build-info\";\nimport { authMode, isConfigured, loadConfig, setupInstructions } from \"#/config\";\nimport { createServer } from \"#/server\";\nimport { describeError } from \"#/tools/util\";\n\n// Everything goes to stderr: stdout is the MCP protocol channel, and a stray\n// log line there corrupts the stream.\nconst stderrLogger = {\n debug: (...args: unknown[]) => {\n if (process.env.LOKI_DEBUG) console.error(\"[loki-mcp]\", ...args);\n },\n warn: (...args: unknown[]) => console.error(\"[loki-mcp]\", ...args),\n error: (...args: unknown[]) => console.error(\"[loki-mcp]\", ...args),\n};\n\n/** Show a config mistake as its field messages, not 40 frames of zod internals. */\nconst describeFatal = (err: unknown): string => {\n if (err instanceof ZodError) {\n return err.issues\n .map((issue) => {\n const path = issue.path.join(\".\");\n return path ? `${path}: ${issue.message}` : issue.message;\n })\n .join(\"\\n\");\n }\n return err instanceof Error ? err.message : String(err);\n};\n\nconst main = async (): Promise<void> => {\n stderrLogger.warn(\n `${BUILD_INFO.name}@${BUILD_INFO.version} (git ${BUILD_INFO.gitCommit} ${BUILD_INFO.gitCommitDate}, node ${process.version})`,\n );\n const config = loadConfig();\n const { server, ctx } = createServer({ config, logger: stderrLogger });\n const transport = new StdioServerTransport();\n await server.connect(transport);\n stderrLogger.warn(\n `loki-mcp connected (url=${config.url ?? \"MISSING\"}, auth=${authMode(config)}, ` +\n `tenant=${ctx.tenant?.tenant ?? \"none\"}, read-only)`,\n );\n for (const line of setupInstructions(config)) stderrLogger.warn(line);\n\n // Which Loki answered, after connecting so a slow one never delays the\n // handshake. The tenant line scrolling past is the cheapest chance to notice\n // a credential copied from the wrong project.\n if (isConfigured(config)) {\n ctx\n .identity()\n .then((id) => {\n const l = id.limits ?? {};\n stderrLogger.warn(\n `loki ${id.version ?? \"?\"} at ${new URL(config.url as string).host}` +\n (ctx.tenant ? `, tenant ${ctx.tenant.tenant}` : \"\") +\n (l.retention ? `, retention ${l.retention}` : \"\") +\n (l.maxQueryLength ? `, max range ${l.maxQueryLength}` : \"\"),\n );\n })\n .catch((err: unknown) => {\n const { error, remedy } = describeError(err);\n stderrLogger.warn(`loki unreachable: ${error}${remedy ? ` — ${String(remedy)}` : \"\"}`);\n });\n }\n\n const shutdown = (signal: string): void => {\n stderrLogger.warn(`received ${signal}, shutting down`);\n process.exit(0);\n };\n process.on(\"SIGINT\", () => shutdown(\"SIGINT\"));\n process.on(\"SIGTERM\", () => shutdown(\"SIGTERM\"));\n};\n\nmain().catch((err: unknown) => {\n console.error(`[loki-mcp] fatal: ${describeFatal(err)}`);\n process.exit(1);\n});\n"],"mappings":";;;;;AAWA,MAAM,eAAe;CACnB,QAAQ,GAAG,SAAoB;EAC7B,IAAI,QAAQ,IAAI,YAAY,QAAQ,MAAM,cAAc,GAAG,IAAI;CACjE;CACA,OAAO,GAAG,SAAoB,QAAQ,MAAM,cAAc,GAAG,IAAI;CACjE,QAAQ,GAAG,SAAoB,QAAQ,MAAM,cAAc,GAAG,IAAI;AACpE;;AAGA,MAAM,iBAAiB,QAAyB;CAC9C,IAAI,eAAe,UACjB,OAAO,IAAI,OACR,KAAK,UAAU;EACd,MAAM,OAAO,MAAM,KAAK,KAAK,GAAG;EAChC,OAAO,OAAO,GAAG,KAAK,IAAI,MAAM,YAAY,MAAM;CACpD,CAAC,CAAC,CACD,KAAK,IAAI;CAEd,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AACxD;AAEA,MAAM,OAAO,YAA2B;CACtC,aAAa,KACX,GAAG,WAAW,KAAK,GAAG,WAAW,QAAQ,QAAQ,WAAW,UAAU,GAAG,WAAW,cAAc,SAAS,QAAQ,QAAQ,EAC7H;CACA,MAAM,SAAS,WAAW;CAC1B,MAAM,EAAE,QAAQ,QAAQ,aAAa;EAAE;EAAQ,QAAQ;CAAa,CAAC;CACrE,MAAM,YAAY,IAAI,qBAAqB;CAC3C,MAAM,OAAO,QAAQ,SAAS;CAC9B,aAAa,KACX,2BAA2B,OAAO,OAAO,UAAU,SAAS,SAAS,MAAM,EAAE,WACjE,IAAI,QAAQ,UAAU,OAAO,aAC3C;CACA,KAAK,MAAM,QAAQ,kBAAkB,MAAM,GAAG,aAAa,KAAK,IAAI;CAKpE,IAAI,aAAa,MAAM,GACrB,IACG,SAAS,CAAC,CACV,MAAM,OAAO;EACZ,MAAM,IAAI,GAAG,UAAU,CAAC;EACxB,aAAa,KACX,QAAQ,GAAG,WAAW,IAAI,MAAM,IAAI,IAAI,OAAO,GAAa,CAAC,CAAC,UAC3D,IAAI,SAAS,YAAY,IAAI,OAAO,WAAW,OAC/C,EAAE,YAAY,eAAe,EAAE,cAAc,OAC7C,EAAE,iBAAiB,eAAe,EAAE,mBAAmB,GAC5D;CACF,CAAC,CAAC,CACD,OAAO,QAAiB;EACvB,MAAM,EAAE,OAAO,WAAW,cAAc,GAAG;EAC3C,aAAa,KAAK,qBAAqB,QAAQ,SAAS,MAAM,OAAO,MAAM,MAAM,IAAI;CACvF,CAAC;CAGL,MAAM,YAAY,WAAyB;EACzC,aAAa,KAAK,YAAY,OAAO,gBAAgB;EACrD,QAAQ,KAAK,CAAC;CAChB;CACA,QAAQ,GAAG,gBAAgB,SAAS,QAAQ,CAAC;CAC7C,QAAQ,GAAG,iBAAiB,SAAS,SAAS,CAAC;AACjD;AAEA,KAAK,CAAC,CAAC,OAAO,QAAiB;CAC7B,QAAQ,MAAM,qBAAqB,cAAc,GAAG,GAAG;CACvD,QAAQ,KAAK,CAAC;AAChB,CAAC"}
@@ -0,0 +1,168 @@
1
+ import { McpServer } from "@modelcontextprotocol/server";
2
+ import { z } from "zod";
3
+ declare const ConfigSchema: z.ZodObject<{
4
+ url: z.ZodOptional<z.ZodURL>;
5
+ username: z.ZodOptional<z.ZodString>;
6
+ password: z.ZodOptional<z.ZodString>;
7
+ token: z.ZodOptional<z.ZodString>;
8
+ tenantId: z.ZodOptional<z.ZodString>;
9
+ headers: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
10
+ timeoutSeconds: z.ZodDefault<z.ZodNumber>;
11
+ maxRetries: z.ZodDefault<z.ZodNumber>;
12
+ problems: z.ZodDefault<z.ZodArray<z.ZodString>>;
13
+ }, z.core.$strict>;
14
+ type Config = z.infer<typeof ConfigSchema>;
15
+ type AuthMode = "basic" | "bearer" | "none";
16
+ /**
17
+ * Environment only: the server persists nothing of its own, so there is no
18
+ * config file to merge with.
19
+ */
20
+ export declare const loadConfig: (env?: NodeJS.ProcessEnv) => Config;
21
+ export declare const authMode: (config: Config) => AuthMode;
22
+ /** A URL and no contradictions. A local Loki needs no auth, so none is required. */
23
+ export declare const isConfigured: (config: Config) => boolean;
24
+ type Tenant = {
25
+ tenant: string;
26
+ source: string;
27
+ };
28
+ /**
29
+ * Which tenant's logs every answer comes from. Loki never echoes it back — no
30
+ * endpoint says "you are tenant X" — so this is what the server sends or what
31
+ * the gateway is known to derive, and it is labelled as such.
32
+ *
33
+ * The Loki chart's nginx gateway with basicAuth sets `X-Scope-OrgID` from the
34
+ * basic-auth username and overwrites any header the client sent (observed on
35
+ * Loki 3.7.9 / chart 20.2.1: a bogus X-Scope-OrgID still answered with the
36
+ * user's tenant). So with basic auth the username is the tenant, and a
37
+ * LOKI_TENANT_ID beside it is probably ignored.
38
+ */
39
+ export declare const resolveTenant: (config: Config) => Tenant | undefined;
40
+ /** Returned by loki_auth_status and printed to stderr at startup. */
41
+ export declare const setupInstructions: (config: Config) => string[];
42
+ type Logger = {
43
+ debug?(...args: unknown[]): void;
44
+ warn?(...args: unknown[]): void;
45
+ error?(...args: unknown[]): void;
46
+ };
47
+ /**
48
+ * The headers every request carries. Loki has no login of its own: basic or
49
+ * bearer auth satisfies whatever sits in front of it (the chart's nginx
50
+ * gateway, an ingress, Grafana Cloud), and `X-Scope-OrgID` picks the tenant
51
+ * when Loki runs with `auth_enabled: true`. Nothing to refresh, so a 401 is
52
+ * always final.
53
+ */
54
+ export declare const authHeaders: (config: Config) => Record<string, string>;
55
+ /** Repeated keys (`match[]`) are arrays; undefined values are dropped. */
56
+ type Params = Record<string, string | number | bigint | boolean | string[] | undefined>;
57
+ type LokiResult<T> = {
58
+ data: T;
59
+ warnings?: string[];
60
+ };
61
+ type LokiClientOptions = {
62
+ baseUrl: string;
63
+ headers: Record<string, string>;
64
+ timeoutSeconds: number;
65
+ maxRetries: number;
66
+ userAgent: string;
67
+ fetch?: typeof fetch;
68
+ logger?: Logger;
69
+ };
70
+ export declare class LokiClient {
71
+ readonly baseUrl: string;
72
+ readonly timeoutSeconds: number;
73
+ private readonly headers;
74
+ private readonly maxRetries;
75
+ private readonly userAgent;
76
+ private readonly fetchImpl;
77
+ private readonly logger;
78
+ constructor(opts: LokiClientOptions);
79
+ get<T = unknown>(path: string, params?: Params, headers?: Record<string, string>): Promise<LokiResult<T>>;
80
+ /** A read on an endpoint that also takes a form POST: GET unless the URL would be too long. */
81
+ read<T = unknown>(path: string, params: Params, headers?: Record<string, string>): Promise<LokiResult<T>>;
82
+ request<T = unknown>(method: "GET" | "POST", path: string, opts?: {
83
+ params?: Params;
84
+ form?: Params;
85
+ headers?: Record<string, string>;
86
+ }): Promise<LokiResult<T>>;
87
+ }
88
+ type Limits = {
89
+ retention?: string;
90
+ maxQueryLength?: string;
91
+ maxQueryRange?: string;
92
+ maxQueryLookback?: string;
93
+ maxEntriesPerQuery?: number;
94
+ maxQuerySeries?: number;
95
+ maxQueryBytesRead?: string;
96
+ queryTimeout?: string;
97
+ volumeEnabled?: boolean;
98
+ patternIngesterEnabled?: boolean;
99
+ discoverLogLevels?: boolean;
100
+ };
101
+ type Identity = {
102
+ version?: string;
103
+ revision?: string;
104
+ limits?: Limits;
105
+ /** Endpoints that did not answer: normal on older Loki or a gateway that does not route them. */
106
+ unavailable?: string[];
107
+ };
108
+ export declare const fetchIdentity: (client: LokiClient) => Promise<Identity>;
109
+ type ToolContext = {
110
+ config: Config;
111
+ hasCredentials: boolean;
112
+ /** The tenant every answer is read from, as far as the configuration says. */
113
+ tenant: Tenant | undefined;
114
+ /**
115
+ * Spread first into every data answer. A credential copied from another
116
+ * tenant answers every query with plausible logs from that tenant, so each
117
+ * answer says whose logs they are.
118
+ */
119
+ tag: () => {
120
+ tenant?: string;
121
+ };
122
+ /** Who answered and what it allows, memoized after the first success. */
123
+ identity: () => Promise<Identity>;
124
+ /** Seconds since the epoch; injectable so tests can pin relative times. */
125
+ now: () => number;
126
+ };
127
+ export declare const createToolContext: (client: LokiClient, config: Config, hasCredentials: boolean, now?: () => number) => ToolContext;
128
+ /**
129
+ * Register the tools. Every tool is a read: Loki's mutating endpoints (push,
130
+ * the compactor's delete requests, ruler writes) are deliberately not wrapped,
131
+ * so there is no write flag. `loki_request` is GET-only.
132
+ */
133
+ export declare const registerTools: (server: McpServer, client: LokiClient, ctx: ToolContext) => void;
134
+ export declare const SERVER_NAME: string;
135
+ export declare const SERVER_VERSION: string;
136
+ export declare const USER_AGENT: string;
137
+ type CreateServerOptions = {
138
+ config: Config;
139
+ fetch?: typeof fetch;
140
+ logger?: Logger;
141
+ /** Seconds since the epoch, for relative times; injectable for tests. */
142
+ now?: () => number;
143
+ };
144
+ type CreatedServer = {
145
+ server: McpServer;
146
+ client: LokiClient;
147
+ ctx: ToolContext;
148
+ };
149
+ export declare const createServer: (opts: CreateServerOptions) => CreatedServer;
150
+ export declare class LokiApiError extends Error {
151
+ readonly name: string;
152
+ /** HTTP status, or 0 when no response arrived at all (DNS, TLS, timeout). */
153
+ readonly status: number;
154
+ /**
155
+ * What to do about it, kept separate from `message`: the message says what
156
+ * happened, the remedy is the half a model should act on, and fail() lifts it
157
+ * to a top-level field so it is not buried inside the upstream text.
158
+ */
159
+ readonly remedy: string | undefined;
160
+ readonly errors: unknown;
161
+ constructor(message: string, opts: {
162
+ status: number;
163
+ remedy?: string;
164
+ errors?: unknown;
165
+ });
166
+ }
167
+ export type { Config, CreateServerOptions, CreatedServer, Identity, Limits, Logger, LokiClientOptions, LokiResult, Params, Tenant, ToolContext };
168
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/config.ts","../src/client/auth.ts","../src/client/loki.ts","../src/client/identity.ts","../src/tools/index.ts","../src/server.ts","../src/client/errors.ts"],"mappings":";;cAEM,cAAY,EAAA;;;;;;;;;;GA+BP,EAAA,KAAA;KAEC,SAAS,EAAE,aAAa;KAExB;;;;;qBA4CC,aAAU,MAAS,OAAO,eAA2B;qBA6DrD,WAAQ,QAAY,WAAS;;qBAI7B,eAAY,QAAY;KAGzB;EAAW;EAAgB;;;;;;;;;;;;;qBAa1B,gBAAa,QAAY,WAAS;;qBAkBlC,oBAAiB,QAAY;KClL9B;EACV,UAAU;EACV,SAAS;EACT,UAAU;;;;;;;;;qBAUC,cAAW,QAAY,WAAS;;KCSjC,SAAS;KAET,WAAW;EAAO,MAAM;EAAG;;KAuG3B;EACV;EACA,SAAS;EACT;EACA;EACA;EACA,eAAe;EACf,SAAS;;qBAGE;WACF;WACA;mBACQ;mBACA;mBACA;mBACA;mBACA;EAEjB,YAAY,MAAM;EAUZ,IAAI,aACR,cACA,SAAS,QACT,UAAU,yBACT,QAAQ,WAAW;;EAKhB,KAAK,aACT,cACA,QAAQ,QACR,UAAU,yBACT,QAAQ,WAAW;EAQhB,QAAQ,aACZ,wBACA,cACA;IAAQ,SAAS;IAAQ,OAAO;IAAQ,UAAU;MACjD,QAAQ,WAAW;;KC7KZ;EACV;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;KAGU;EACV;EACA;EACA,SAAS;;EAET;;qBAmCW,gBAAa,QAAkB,eAAa,QAAQ;KCnDrD;EACV,QAAQ;EACR;;EAEA,QAAQ;;;;;;EAMR;IAAa;;;EAEb,gBAAgB,QAAQ;;EAExB;;qBAGW,oBAAiB,QACpB,YAAU,QACV,QAAM,yBACS,uBAEtB;;;;;;qBAyBU,gBAAa,QAAY,WAAS,QAAU,YAAU,KAAO;qBCpD7D;qBACA;qBACA;KAED;EACV,QAAQ;EACR,eAAe;EACf,SAAS;;EAET;;KAGU;EACV,QAAQ;EACR,QAAQ;EACR,KAAK;;qBAGM,eAAY,MAAU,wBAAsB;qBC1B5C,qBAAqB;WAEd;;WAET;;;;;;WAMA;WACA;EAET,YAAY,iBAAiB;IAAQ;IAAgB;IAAiB"}
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ export { u as LokiApiError, l as LokiClient, t as SERVER_NAME, n as SERVER_VERSION, r as USER_AGENT, d as authHeaders, f as authMode, i as createServer, a as createToolContext, c as fetchIdentity, p as isConfigured, m as loadConfig, o as registerTools, h as resolveTenant, g as setupInstructions } from "./server-B2TOeJ3P.js";