@monocle.sh/studio 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 +15 -0
- package/dist/adonisrc.d.ts +6 -0
- package/dist/adonisrc.js +25 -0
- package/dist/config/app.d.ts +6 -0
- package/dist/config/app.js +5 -0
- package/dist/config/bodyparser.d.ts +4 -0
- package/dist/config/bodyparser.js +5 -0
- package/dist/config/encryption.d.ts +12 -0
- package/dist/config/encryption.js +11 -0
- package/dist/config/logger.d.ts +4 -0
- package/dist/config/logger.js +13 -0
- package/dist/config/static.d.ts +6 -0
- package/dist/config/static.js +11 -0
- package/dist/controllers/api_controller.d.ts +174 -0
- package/dist/controllers/api_controller.js +118 -0
- package/dist/controllers/mcp_controller.d.ts +20 -0
- package/dist/controllers/mcp_controller.js +29 -0
- package/dist/controllers/otlp_controller.d.ts +52 -0
- package/dist/controllers/otlp_controller.js +92 -0
- package/dist/controllers/sse_controller.d.ts +18 -0
- package/dist/controllers/sse_controller.js +36 -0
- package/dist/db/connection.d.ts +20 -0
- package/dist/db/connection.js +38 -0
- package/dist/db/schema.d.ts +10 -0
- package/dist/db/schema.js +45 -0
- package/dist/db/types.d.ts +40 -0
- package/dist/db/types.js +1 -0
- package/dist/mcp/define_tool.d.ts +10 -0
- package/dist/mcp/define_tool.js +9 -0
- package/dist/mcp/tools/clear_data.d.ts +9 -0
- package/dist/mcp/tools/clear_data.js +26 -0
- package/dist/mcp/tools/get_trace.d.ts +12 -0
- package/dist/mcp/tools/get_trace.js +25 -0
- package/dist/mcp/tools/index.d.ts +10 -0
- package/dist/mcp/tools/index.js +37 -0
- package/dist/mcp/tools/list_errors.d.ts +14 -0
- package/dist/mcp/tools/list_errors.js +25 -0
- package/dist/mcp/tools/list_logs.d.ts +16 -0
- package/dist/mcp/tools/list_logs.js +30 -0
- package/dist/mcp/tools/list_queries.d.ts +15 -0
- package/dist/mcp/tools/list_queries.js +27 -0
- package/dist/mcp/tools/list_traces.d.ts +14 -0
- package/dist/mcp/tools/list_traces.js +25 -0
- package/dist/mcp/types.d.ts +21 -0
- package/dist/mcp/types.js +1 -0
- package/dist/mcp.d.ts +2 -0
- package/dist/mcp.js +2 -0
- package/dist/providers/api_provider.d.ts +14 -0
- package/dist/providers/api_provider.js +13 -0
- package/dist/repositories/log_repository.d.ts +43 -0
- package/dist/repositories/log_repository.js +58 -0
- package/dist/repositories/span_repository.d.ts +136 -0
- package/dist/repositories/span_repository.js +254 -0
- package/dist/semconv.d.ts +38 -0
- package/dist/semconv.js +40 -0
- package/dist/server.d.ts +16 -0
- package/dist/server.js +68 -0
- package/dist/services/event_bus.d.ts +24 -0
- package/dist/services/event_bus.js +24 -0
- package/dist/services/otlp_parser.d.ts +21 -0
- package/dist/services/otlp_parser.js +121 -0
- package/dist/start/kernel.d.ts +1 -0
- package/dist/start/kernel.js +5 -0
- package/dist/start/routes.d.ts +1 -0
- package/dist/start/routes.js +35 -0
- package/dist/transformers/command_transformer.d.ts +18 -0
- package/dist/transformers/command_transformer.js +20 -0
- package/dist/transformers/exception_transformer.d.ts +17 -0
- package/dist/transformers/exception_transformer.js +19 -0
- package/dist/transformers/job_transformer.d.ts +18 -0
- package/dist/transformers/job_transformer.js +20 -0
- package/dist/transformers/log_transformer.d.ts +18 -0
- package/dist/transformers/log_transformer.js +19 -0
- package/dist/transformers/query_transformer.d.ts +20 -0
- package/dist/transformers/query_transformer.js +27 -0
- package/dist/transformers/span_transformer.d.ts +22 -0
- package/dist/transformers/span_transformer.js +23 -0
- package/dist/transformers/trace_transformer.d.ts +22 -0
- package/dist/transformers/trace_transformer.js +33 -0
- package/dist/types/logs.d.ts +19 -0
- package/dist/types/logs.js +1 -0
- package/dist/types/otlp.d.ts +105 -0
- package/dist/types/otlp.js +1 -0
- package/dist/types/spans.d.ts +29 -0
- package/dist/types/spans.js +1 -0
- package/dist/validators.d.ts +103 -0
- package/dist/validators.js +41 -0
- package/package.json +60 -0
- package/ui/dist/assets/geist-cyrillic-wght-normal-CHSlOQsW.woff2 +0 -0
- package/ui/dist/assets/geist-latin-ext-wght-normal-DMtmJ5ZE.woff2 +0 -0
- package/ui/dist/assets/geist-latin-wght-normal-Dm3htQBi.woff2 +0 -0
- package/ui/dist/assets/index-Bfk6GRvP.css +1 -0
- package/ui/dist/assets/index-XOaGlb1r.js +115 -0
- package/ui/dist/assets/jetbrains-mono-cyrillic-wght-normal-D73BlboJ.woff2 +0 -0
- package/ui/dist/assets/jetbrains-mono-greek-wght-normal-Bw9x6K1M.woff2 +0 -0
- package/ui/dist/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
- package/ui/dist/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
- package/ui/dist/assets/jetbrains-mono-vietnamese-wght-normal-Bt-aOZkq.woff2 +0 -0
- package/ui/dist/assets/silkscreen-latin-400-normal-CtPo2yA5.woff2 +0 -0
- package/ui/dist/assets/silkscreen-latin-400-normal-D0DfPJut.woff +0 -0
- package/ui/dist/favicon.svg +4 -0
- package/ui/dist/index.html +14 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Database } from "./types.js";
|
|
2
|
+
import { Kysely } from "kysely";
|
|
3
|
+
|
|
4
|
+
//#region src/db/connection.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Initializes a DuckDB connection at the given file path
|
|
7
|
+
* and returns a typed Kysely instance.
|
|
8
|
+
*/
|
|
9
|
+
declare function initConnection(dbPath: string): Promise<Kysely<Database>>;
|
|
10
|
+
/**
|
|
11
|
+
* Returns the active DuckDB Kysely instance, or throws
|
|
12
|
+
* if the connection has not been initialized yet.
|
|
13
|
+
*/
|
|
14
|
+
declare function getDb(): Kysely<Database>;
|
|
15
|
+
/**
|
|
16
|
+
* Gracefully destroys the DuckDB connection and resets the singleton.
|
|
17
|
+
*/
|
|
18
|
+
declare function closeConnection(): Promise<void>;
|
|
19
|
+
//#endregion
|
|
20
|
+
export { closeConnection, getDb, initConnection };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Kysely } from "kysely";
|
|
2
|
+
import { mkdirSync } from "node:fs";
|
|
3
|
+
import { dirname } from "node:path";
|
|
4
|
+
import { DuckDBInstance } from "@duckdb/node-api";
|
|
5
|
+
import { DuckDbDialect } from "kysely-duckdb";
|
|
6
|
+
//#region src/db/connection.ts
|
|
7
|
+
let db = null;
|
|
8
|
+
/**
|
|
9
|
+
* Initializes a DuckDB connection at the given file path
|
|
10
|
+
* and returns a typed Kysely instance.
|
|
11
|
+
*/
|
|
12
|
+
async function initConnection(dbPath) {
|
|
13
|
+
mkdirSync(dirname(dbPath), { recursive: true });
|
|
14
|
+
db = new Kysely({ dialect: new DuckDbDialect({
|
|
15
|
+
database: await DuckDBInstance.create(dbPath),
|
|
16
|
+
tableMappings: {}
|
|
17
|
+
}) });
|
|
18
|
+
return db;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Returns the active DuckDB Kysely instance, or throws
|
|
22
|
+
* if the connection has not been initialized yet.
|
|
23
|
+
*/
|
|
24
|
+
function getDb() {
|
|
25
|
+
if (!db) throw new Error("DuckDB connection not initialized. Call initConnection() first.");
|
|
26
|
+
return db;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Gracefully destroys the DuckDB connection and resets the singleton.
|
|
30
|
+
*/
|
|
31
|
+
async function closeConnection() {
|
|
32
|
+
if (db) {
|
|
33
|
+
await db.destroy();
|
|
34
|
+
db = null;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
//#endregion
|
|
38
|
+
export { closeConnection, getDb, initConnection };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Database } from "./types.js";
|
|
2
|
+
import { Kysely } from "kysely";
|
|
3
|
+
|
|
4
|
+
//#region src/db/schema.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Creates the spans and logs tables if they don't already exist.
|
|
7
|
+
*/
|
|
8
|
+
declare function initializeSchema(db: Kysely<Database>): Promise<void>;
|
|
9
|
+
//#endregion
|
|
10
|
+
export { initializeSchema };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { sql } from "kysely";
|
|
2
|
+
//#region src/db/schema.ts
|
|
3
|
+
/**
|
|
4
|
+
* Creates the spans and logs tables if they don't already exist.
|
|
5
|
+
*/
|
|
6
|
+
async function initializeSchema(db) {
|
|
7
|
+
await sql`
|
|
8
|
+
CREATE TABLE IF NOT EXISTS spans (
|
|
9
|
+
trace_id VARCHAR NOT NULL,
|
|
10
|
+
span_id VARCHAR NOT NULL,
|
|
11
|
+
parent_span_id VARCHAR,
|
|
12
|
+
span_name VARCHAR NOT NULL,
|
|
13
|
+
span_kind VARCHAR,
|
|
14
|
+
service_name VARCHAR,
|
|
15
|
+
status_code VARCHAR DEFAULT 'UNSET',
|
|
16
|
+
status_message VARCHAR,
|
|
17
|
+
start_time_unix BIGINT NOT NULL,
|
|
18
|
+
end_time_unix BIGINT NOT NULL,
|
|
19
|
+
duration_ns BIGINT NOT NULL,
|
|
20
|
+
resource_attributes JSON,
|
|
21
|
+
span_attributes JSON,
|
|
22
|
+
scope_name VARCHAR,
|
|
23
|
+
scope_version VARCHAR,
|
|
24
|
+
events JSON,
|
|
25
|
+
PRIMARY KEY (trace_id, span_id)
|
|
26
|
+
)
|
|
27
|
+
`.execute(db);
|
|
28
|
+
await sql`
|
|
29
|
+
CREATE TABLE IF NOT EXISTS logs (
|
|
30
|
+
timestamp_unix BIGINT NOT NULL,
|
|
31
|
+
trace_id VARCHAR,
|
|
32
|
+
span_id VARCHAR,
|
|
33
|
+
severity_text VARCHAR,
|
|
34
|
+
severity_number INTEGER,
|
|
35
|
+
service_name VARCHAR,
|
|
36
|
+
body VARCHAR,
|
|
37
|
+
resource_attributes JSON,
|
|
38
|
+
log_attributes JSON,
|
|
39
|
+
scope_name VARCHAR,
|
|
40
|
+
scope_version VARCHAR
|
|
41
|
+
)
|
|
42
|
+
`.execute(db);
|
|
43
|
+
}
|
|
44
|
+
//#endregion
|
|
45
|
+
export { initializeSchema };
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Generated } from "kysely";
|
|
2
|
+
|
|
3
|
+
//#region src/db/types.d.ts
|
|
4
|
+
interface SpansTable {
|
|
5
|
+
trace_id: string;
|
|
6
|
+
span_id: string;
|
|
7
|
+
parent_span_id: string | null;
|
|
8
|
+
span_name: string;
|
|
9
|
+
span_kind: string | null;
|
|
10
|
+
service_name: string | null;
|
|
11
|
+
status_code: Generated<string>;
|
|
12
|
+
status_message: string | null;
|
|
13
|
+
start_time_unix: bigint;
|
|
14
|
+
end_time_unix: bigint;
|
|
15
|
+
duration_ns: bigint;
|
|
16
|
+
resource_attributes: string | null;
|
|
17
|
+
span_attributes: string | null;
|
|
18
|
+
scope_name: string | null;
|
|
19
|
+
scope_version: string | null;
|
|
20
|
+
events: string | null;
|
|
21
|
+
}
|
|
22
|
+
interface LogsTable {
|
|
23
|
+
timestamp_unix: bigint;
|
|
24
|
+
trace_id: string | null;
|
|
25
|
+
span_id: string | null;
|
|
26
|
+
severity_text: string | null;
|
|
27
|
+
severity_number: number | null;
|
|
28
|
+
service_name: string | null;
|
|
29
|
+
body: string | null;
|
|
30
|
+
resource_attributes: string | null;
|
|
31
|
+
log_attributes: string | null;
|
|
32
|
+
scope_name: string | null;
|
|
33
|
+
scope_version: string | null;
|
|
34
|
+
}
|
|
35
|
+
interface Database {
|
|
36
|
+
spans: SpansTable;
|
|
37
|
+
logs: LogsTable;
|
|
38
|
+
}
|
|
39
|
+
//#endregion
|
|
40
|
+
export { Database, LogsTable, SpansTable };
|
package/dist/db/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ToolDefinition } from "./types.js";
|
|
2
|
+
import { ZodRawShape } from "zod";
|
|
3
|
+
|
|
4
|
+
//#region src/mcp/define_tool.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Type-safe factory for defining MCP tools with Zod schema validation.
|
|
7
|
+
*/
|
|
8
|
+
declare function defineTool<TSchema extends ZodRawShape>(options: ToolDefinition<TSchema>): ToolDefinition<TSchema>;
|
|
9
|
+
//#endregion
|
|
10
|
+
export { defineTool };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ToolDefinition } from "../types.js";
|
|
2
|
+
|
|
3
|
+
//#region src/mcp/tools/clear_data.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* MCP tool: clears all collected traces and logs for a fresh session.
|
|
6
|
+
*/
|
|
7
|
+
declare const clearDataTool: ToolDefinition<{}>;
|
|
8
|
+
//#endregion
|
|
9
|
+
export { clearDataTool };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { SpanRepository } from "../../repositories/span_repository.js";
|
|
2
|
+
import { defineTool } from "../define_tool.js";
|
|
3
|
+
import { LogRepository } from "../../repositories/log_repository.js";
|
|
4
|
+
//#region src/mcp/tools/clear_data.ts
|
|
5
|
+
/**
|
|
6
|
+
* MCP tool: clears all collected traces and logs for a fresh session.
|
|
7
|
+
*/
|
|
8
|
+
const clearDataTool = defineTool({
|
|
9
|
+
name: "clear_data",
|
|
10
|
+
description: "Clear all collected traces, logs, and queries. Useful for starting a fresh debugging session.",
|
|
11
|
+
schema: {},
|
|
12
|
+
annotations: {
|
|
13
|
+
destructiveHint: true,
|
|
14
|
+
readOnlyHint: false,
|
|
15
|
+
idempotentHint: true
|
|
16
|
+
},
|
|
17
|
+
async execute() {
|
|
18
|
+
const spanRepo = new SpanRepository();
|
|
19
|
+
const logRepo = new LogRepository();
|
|
20
|
+
await spanRepo.clearAll();
|
|
21
|
+
await logRepo.clearAll();
|
|
22
|
+
return { message: "All telemetry data cleared." };
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
//#endregion
|
|
26
|
+
export { clearDataTool };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ToolDefinition } from "../types.js";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
|
|
4
|
+
//#region src/mcp/tools/get_trace.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* MCP tool: retrieves the full span waterfall for a given trace ID.
|
|
7
|
+
*/
|
|
8
|
+
declare const getTraceTool: ToolDefinition<{
|
|
9
|
+
traceId: z.ZodString;
|
|
10
|
+
}>;
|
|
11
|
+
//#endregion
|
|
12
|
+
export { getTraceTool };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { SpanRepository } from "../../repositories/span_repository.js";
|
|
2
|
+
import { defineTool } from "../define_tool.js";
|
|
3
|
+
import SpanTransformer from "../../transformers/span_transformer.js";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
//#region src/mcp/tools/get_trace.ts
|
|
6
|
+
/**
|
|
7
|
+
* MCP tool: retrieves the full span waterfall for a given trace ID.
|
|
8
|
+
*/
|
|
9
|
+
const getTraceTool = defineTool({
|
|
10
|
+
name: "get_trace",
|
|
11
|
+
description: "Get all spans for a specific trace. Returns the complete waterfall with parent/child relationships, durations, and attributes.",
|
|
12
|
+
schema: { traceId: z.string().describe("The trace ID to look up") },
|
|
13
|
+
async execute(params) {
|
|
14
|
+
const rows = await new SpanRepository().getTraceSpans(params.traceId);
|
|
15
|
+
if (!rows.length) return { error: "Trace not found" };
|
|
16
|
+
const spans = rows.map((row) => new SpanTransformer(row).toObject());
|
|
17
|
+
return {
|
|
18
|
+
traceId: params.traceId,
|
|
19
|
+
spanCount: spans.length,
|
|
20
|
+
spans
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
//#endregion
|
|
25
|
+
export { getTraceTool };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
|
|
3
|
+
//#region src/mcp/tools/index.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Registers all devtools MCP tools on the given server instance,
|
|
6
|
+
* wrapping each tool's result as a JSON text content block.
|
|
7
|
+
*/
|
|
8
|
+
declare function registerAllTools(server: McpServer): void;
|
|
9
|
+
//#endregion
|
|
10
|
+
export { registerAllTools };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { listTracesTool } from "./list_traces.js";
|
|
2
|
+
import { getTraceTool } from "./get_trace.js";
|
|
3
|
+
import { listLogsTool } from "./list_logs.js";
|
|
4
|
+
import { listErrorsTool } from "./list_errors.js";
|
|
5
|
+
import { listQueriesTool } from "./list_queries.js";
|
|
6
|
+
import { clearDataTool } from "./clear_data.js";
|
|
7
|
+
//#region src/mcp/tools/index.ts
|
|
8
|
+
const tools = [
|
|
9
|
+
listTracesTool,
|
|
10
|
+
getTraceTool,
|
|
11
|
+
listLogsTool,
|
|
12
|
+
listErrorsTool,
|
|
13
|
+
listQueriesTool,
|
|
14
|
+
clearDataTool
|
|
15
|
+
];
|
|
16
|
+
/**
|
|
17
|
+
* Registers all devtools MCP tools on the given server instance,
|
|
18
|
+
* wrapping each tool's result as a JSON text content block.
|
|
19
|
+
*/
|
|
20
|
+
function registerAllTools(server) {
|
|
21
|
+
for (const tool of tools) server.registerTool(tool.name, {
|
|
22
|
+
description: tool.description,
|
|
23
|
+
inputSchema: tool.schema,
|
|
24
|
+
annotations: tool.annotations ?? {
|
|
25
|
+
readOnlyHint: true,
|
|
26
|
+
idempotentHint: true
|
|
27
|
+
}
|
|
28
|
+
}, async (params) => {
|
|
29
|
+
const result = await tool.execute(params);
|
|
30
|
+
return { content: [{
|
|
31
|
+
type: "text",
|
|
32
|
+
text: JSON.stringify(result, null, 2)
|
|
33
|
+
}] };
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
//#endregion
|
|
37
|
+
export { registerAllTools };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ToolDefinition } from "../types.js";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
|
|
4
|
+
//#region src/mcp/tools/list_errors.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* MCP tool: lists captured exceptions with type, message, and stacktrace.
|
|
7
|
+
*/
|
|
8
|
+
declare const listErrorsTool: ToolDefinition<{
|
|
9
|
+
limit: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
10
|
+
offset: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
11
|
+
traceId: z.ZodOptional<z.ZodString>;
|
|
12
|
+
}>;
|
|
13
|
+
//#endregion
|
|
14
|
+
export { listErrorsTool };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { SpanRepository } from "../../repositories/span_repository.js";
|
|
2
|
+
import { defineTool } from "../define_tool.js";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
//#region src/mcp/tools/list_errors.ts
|
|
5
|
+
/**
|
|
6
|
+
* MCP tool: lists captured exceptions with type, message, and stacktrace.
|
|
7
|
+
*/
|
|
8
|
+
const listErrorsTool = defineTool({
|
|
9
|
+
name: "list_errors",
|
|
10
|
+
description: "List exceptions and errors captured during request processing. Returns exception type, message, stacktrace, and associated trace for debugging.",
|
|
11
|
+
schema: {
|
|
12
|
+
limit: z.number().optional().default(50).describe("Number of results (max 100)"),
|
|
13
|
+
offset: z.number().optional().default(0).describe("Offset for pagination"),
|
|
14
|
+
traceId: z.string().optional().describe("Filter errors for a specific trace")
|
|
15
|
+
},
|
|
16
|
+
async execute(params) {
|
|
17
|
+
return new SpanRepository().listExceptions({
|
|
18
|
+
limit: Math.min(params.limit, 100),
|
|
19
|
+
offset: params.offset,
|
|
20
|
+
traceId: params.traceId
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
//#endregion
|
|
25
|
+
export { listErrorsTool };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ToolDefinition } from "../types.js";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
|
|
4
|
+
//#region src/mcp/tools/list_logs.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* MCP tool: lists application logs with severity/search/trace filters.
|
|
7
|
+
*/
|
|
8
|
+
declare const listLogsTool: ToolDefinition<{
|
|
9
|
+
limit: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
10
|
+
offset: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
11
|
+
severity: z.ZodOptional<z.ZodString>;
|
|
12
|
+
search: z.ZodOptional<z.ZodString>;
|
|
13
|
+
traceId: z.ZodOptional<z.ZodString>;
|
|
14
|
+
}>;
|
|
15
|
+
//#endregion
|
|
16
|
+
export { listLogsTool };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { defineTool } from "../define_tool.js";
|
|
2
|
+
import { LogRepository } from "../../repositories/log_repository.js";
|
|
3
|
+
import LogTransformer from "../../transformers/log_transformer.js";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
//#region src/mcp/tools/list_logs.ts
|
|
6
|
+
/**
|
|
7
|
+
* MCP tool: lists application logs with severity/search/trace filters.
|
|
8
|
+
*/
|
|
9
|
+
const listLogsTool = defineTool({
|
|
10
|
+
name: "list_logs",
|
|
11
|
+
description: "List application logs with filtering by severity, search text, or trace ID. Useful for debugging and understanding application behavior.",
|
|
12
|
+
schema: {
|
|
13
|
+
limit: z.number().optional().default(50).describe("Number of results (max 500)"),
|
|
14
|
+
offset: z.number().optional().default(0).describe("Offset for pagination"),
|
|
15
|
+
severity: z.string().optional().describe("Filter by severity: trace, debug, info, warn, error, fatal"),
|
|
16
|
+
search: z.string().optional().describe("Search in log messages and attributes"),
|
|
17
|
+
traceId: z.string().optional().describe("Filter by trace ID to see logs for a specific request")
|
|
18
|
+
},
|
|
19
|
+
async execute(params) {
|
|
20
|
+
return (await new LogRepository().listLogs({
|
|
21
|
+
limit: Math.min(params.limit, 500),
|
|
22
|
+
offset: params.offset,
|
|
23
|
+
severity: params.severity,
|
|
24
|
+
search: params.search,
|
|
25
|
+
traceId: params.traceId
|
|
26
|
+
})).map((row) => new LogTransformer(row).toObject());
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
//#endregion
|
|
30
|
+
export { listLogsTool };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ToolDefinition } from "../types.js";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
|
|
4
|
+
//#region src/mcp/tools/list_queries.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* MCP tool: lists database queries with SQL, duration, and DB system.
|
|
7
|
+
*/
|
|
8
|
+
declare const listQueriesTool: ToolDefinition<{
|
|
9
|
+
limit: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
10
|
+
offset: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
11
|
+
traceId: z.ZodOptional<z.ZodString>;
|
|
12
|
+
dbSystem: z.ZodOptional<z.ZodString>;
|
|
13
|
+
}>;
|
|
14
|
+
//#endregion
|
|
15
|
+
export { listQueriesTool };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { SpanRepository } from "../../repositories/span_repository.js";
|
|
2
|
+
import { defineTool } from "../define_tool.js";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
//#region src/mcp/tools/list_queries.ts
|
|
5
|
+
/**
|
|
6
|
+
* MCP tool: lists database queries with SQL, duration, and DB system.
|
|
7
|
+
*/
|
|
8
|
+
const listQueriesTool = defineTool({
|
|
9
|
+
name: "list_queries",
|
|
10
|
+
description: "List database queries with performance data. Returns SQL statements, operations, database system, duration, and associated trace. Use dbSystem filter to narrow by database (postgresql, mysql, sqlite, etc.).",
|
|
11
|
+
schema: {
|
|
12
|
+
limit: z.number().optional().default(50).describe("Number of results (max 100)"),
|
|
13
|
+
offset: z.number().optional().default(0).describe("Offset for pagination"),
|
|
14
|
+
traceId: z.string().optional().describe("Filter queries for a specific trace"),
|
|
15
|
+
dbSystem: z.string().optional().describe("Filter by database system (e.g., postgresql, mysql, sqlite)")
|
|
16
|
+
},
|
|
17
|
+
async execute(params) {
|
|
18
|
+
return new SpanRepository().listQueries({
|
|
19
|
+
limit: Math.min(params.limit, 100),
|
|
20
|
+
offset: params.offset,
|
|
21
|
+
traceId: params.traceId,
|
|
22
|
+
dbSystem: params.dbSystem
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
//#endregion
|
|
27
|
+
export { listQueriesTool };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ToolDefinition } from "../types.js";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
|
|
4
|
+
//#region src/mcp/tools/list_traces.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* MCP tool: lists recent HTTP request traces with pagination.
|
|
7
|
+
*/
|
|
8
|
+
declare const listTracesTool: ToolDefinition<{
|
|
9
|
+
limit: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
10
|
+
offset: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
11
|
+
traceId: z.ZodOptional<z.ZodString>;
|
|
12
|
+
}>;
|
|
13
|
+
//#endregion
|
|
14
|
+
export { listTracesTool };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { SpanRepository } from "../../repositories/span_repository.js";
|
|
2
|
+
import { defineTool } from "../define_tool.js";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
//#region src/mcp/tools/list_traces.ts
|
|
5
|
+
/**
|
|
6
|
+
* MCP tool: lists recent HTTP request traces with pagination.
|
|
7
|
+
*/
|
|
8
|
+
const listTracesTool = defineTool({
|
|
9
|
+
name: "list_traces",
|
|
10
|
+
description: "List recent traces with summary data. Use this to explore request flows, filter by status to surface errors, or find slow requests.",
|
|
11
|
+
schema: {
|
|
12
|
+
limit: z.number().optional().default(25).describe("Number of results (max 100)"),
|
|
13
|
+
offset: z.number().optional().default(0).describe("Offset for pagination"),
|
|
14
|
+
traceId: z.string().optional().describe("Filter by trace ID")
|
|
15
|
+
},
|
|
16
|
+
async execute(params) {
|
|
17
|
+
return await new SpanRepository().listTraces({
|
|
18
|
+
limit: Math.min(params.limit, 100),
|
|
19
|
+
offset: params.offset,
|
|
20
|
+
traceId: params.traceId
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
//#endregion
|
|
25
|
+
export { listTracesTool };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ZodObject, ZodRawShape, z } from "zod";
|
|
2
|
+
|
|
3
|
+
//#region src/mcp/types.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Describes an MCP tool: its name, human-readable description,
|
|
6
|
+
* Zod input schema, and async execute handler.
|
|
7
|
+
*/
|
|
8
|
+
interface ToolAnnotations {
|
|
9
|
+
readOnlyHint?: boolean;
|
|
10
|
+
idempotentHint?: boolean;
|
|
11
|
+
destructiveHint?: boolean;
|
|
12
|
+
}
|
|
13
|
+
interface ToolDefinition<TSchema extends ZodRawShape = ZodRawShape> {
|
|
14
|
+
name: string;
|
|
15
|
+
description: string;
|
|
16
|
+
schema: TSchema;
|
|
17
|
+
annotations?: ToolAnnotations;
|
|
18
|
+
execute: (params: z.infer<ZodObject<TSchema>>) => Promise<unknown>;
|
|
19
|
+
}
|
|
20
|
+
//#endregion
|
|
21
|
+
export { ToolAnnotations, ToolDefinition };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/mcp.d.ts
ADDED
package/dist/mcp.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { BaseSerializer } from "@adonisjs/core/transformers";
|
|
2
|
+
|
|
3
|
+
//#region src/providers/api_provider.d.ts
|
|
4
|
+
declare class ApiSerializer extends BaseSerializer<{
|
|
5
|
+
Wrap: undefined;
|
|
6
|
+
}> {
|
|
7
|
+
wrap: undefined;
|
|
8
|
+
definePaginationMetaData(metaData: unknown): unknown;
|
|
9
|
+
}
|
|
10
|
+
declare module '@adonisjs/core/http' {
|
|
11
|
+
interface HttpContext {
|
|
12
|
+
serialize: ApiSerializer['serialize'];
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { BaseSerializer } from "@adonisjs/core/transformers";
|
|
2
|
+
import { HttpContext } from "@adonisjs/core/http";
|
|
3
|
+
//#region src/providers/api_provider.ts
|
|
4
|
+
var ApiSerializer = class extends BaseSerializer {
|
|
5
|
+
wrap = void 0;
|
|
6
|
+
definePaginationMetaData(metaData) {
|
|
7
|
+
return metaData;
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
const serializer = new ApiSerializer();
|
|
11
|
+
HttpContext.instanceProperty("serialize", serializer.serialize.bind(serializer));
|
|
12
|
+
//#endregion
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { FlatLog } from "../types/logs.js";
|
|
2
|
+
|
|
3
|
+
//#region src/repositories/log_repository.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Data-access layer for application logs stored in DuckDB.
|
|
6
|
+
* Supports inserting, listing with filters, and clearing log data.
|
|
7
|
+
*/
|
|
8
|
+
declare class LogRepository {
|
|
9
|
+
#private;
|
|
10
|
+
/**
|
|
11
|
+
* Inserts a batch of flat log entries into the logs table.
|
|
12
|
+
*/
|
|
13
|
+
insertLogs(logs: FlatLog[]): Promise<void>;
|
|
14
|
+
/**
|
|
15
|
+
* Deletes all rows from the logs table.
|
|
16
|
+
*/
|
|
17
|
+
clearAll(): Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* Lists logs with optional filtering by severity, full-text
|
|
20
|
+
* search (body + attributes), and trace ID correlation.
|
|
21
|
+
*/
|
|
22
|
+
listLogs(options?: {
|
|
23
|
+
limit?: number;
|
|
24
|
+
offset?: number;
|
|
25
|
+
severity?: string;
|
|
26
|
+
search?: string;
|
|
27
|
+
traceId?: string;
|
|
28
|
+
}): Promise<{
|
|
29
|
+
trace_id: string | null;
|
|
30
|
+
span_id: string | null;
|
|
31
|
+
service_name: string | null;
|
|
32
|
+
timestamp_unix: bigint;
|
|
33
|
+
severity_text: string | null;
|
|
34
|
+
severity_number: number | null;
|
|
35
|
+
body: string | null;
|
|
36
|
+
resource_attributes: string | null;
|
|
37
|
+
log_attributes: string | null;
|
|
38
|
+
scope_name: string | null;
|
|
39
|
+
scope_version: string | null;
|
|
40
|
+
}[]>;
|
|
41
|
+
}
|
|
42
|
+
//#endregion
|
|
43
|
+
export { LogRepository };
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { getDb } from "../db/connection.js";
|
|
2
|
+
import { sql } from "kysely";
|
|
3
|
+
//#region src/repositories/log_repository.ts
|
|
4
|
+
/**
|
|
5
|
+
* Data-access layer for application logs stored in DuckDB.
|
|
6
|
+
* Supports inserting, listing with filters, and clearing log data.
|
|
7
|
+
*/
|
|
8
|
+
var LogRepository = class {
|
|
9
|
+
/**
|
|
10
|
+
* Serializes a value to JSON, returning null for falsy values.
|
|
11
|
+
*/
|
|
12
|
+
#jsonOrNull(value) {
|
|
13
|
+
if (!value) return null;
|
|
14
|
+
return JSON.stringify(value);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Inserts a batch of flat log entries into the logs table.
|
|
18
|
+
*/
|
|
19
|
+
async insertLogs(logs) {
|
|
20
|
+
const db = getDb();
|
|
21
|
+
for (const log of logs) await db.insertInto("logs").values({
|
|
22
|
+
timestamp_unix: log.timestampUnix,
|
|
23
|
+
trace_id: log.traceId,
|
|
24
|
+
span_id: log.spanId,
|
|
25
|
+
severity_text: log.severityText,
|
|
26
|
+
severity_number: log.severityNumber,
|
|
27
|
+
service_name: log.serviceName,
|
|
28
|
+
body: log.body,
|
|
29
|
+
resource_attributes: this.#jsonOrNull(log.resourceAttributes),
|
|
30
|
+
log_attributes: this.#jsonOrNull(log.logAttributes),
|
|
31
|
+
scope_name: log.scopeName,
|
|
32
|
+
scope_version: log.scopeVersion
|
|
33
|
+
}).execute();
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Deletes all rows from the logs table.
|
|
37
|
+
*/
|
|
38
|
+
async clearAll() {
|
|
39
|
+
const db = getDb();
|
|
40
|
+
await sql`DELETE FROM logs`.execute(db);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Lists logs with optional filtering by severity, full-text
|
|
44
|
+
* search (body + attributes), and trace ID correlation.
|
|
45
|
+
*/
|
|
46
|
+
async listLogs(options = {}) {
|
|
47
|
+
const db = getDb();
|
|
48
|
+
const limit = options.limit ?? 100;
|
|
49
|
+
const offset = options.offset ?? 0;
|
|
50
|
+
let query = db.selectFrom("logs").selectAll().orderBy("timestamp_unix", "desc").limit(limit).offset(offset);
|
|
51
|
+
if (options.traceId) query = query.where("trace_id", "=", options.traceId);
|
|
52
|
+
if (options.severity) query = query.where(sql`UPPER(severity_text)`, "=", sql`UPPER(${options.severity})`);
|
|
53
|
+
if (options.search) query = query.where((eb) => eb.or([eb("body", "ilike", `%${options.search}%`), eb(sql`log_attributes`, "ilike", sql`${"%" + options.search + "%"}`)]));
|
|
54
|
+
return query.execute();
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
//#endregion
|
|
58
|
+
export { LogRepository };
|