@mastra/mcp-docs-server 1.1.18 → 1.1.19

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.
@@ -22,13 +22,70 @@ export const mastra = new Mastra({
22
22
 
23
23
  > **Info:** Visit [PinoLogger](https://mastra.ai/reference/logging/pino-logger) for all available configuration options.
24
24
 
25
+ ## Logging to observability storage
26
+
27
+ When [observability](https://mastra.ai/docs/observability/overview) is configured, all logger calls are automatically forwarded to your observability storage. This means every `debug`, `info`, `warn`, `error`, and `trackException` call from your application and from Mastra's internal components appears alongside your traces.
28
+
29
+ No code changes are required. Mastra wraps the configured logger so that it writes to both the original logger (console, file, or custom transport) and the observability system simultaneously.
30
+
31
+ ### Configuring observability log level
32
+
33
+ You can control which log levels reach observability storage independently from your console logger. Add a `logging` option to your observability instance configuration:
34
+
35
+ ```typescript
36
+ import { Mastra } from '@mastra/core/mastra'
37
+ import { PinoLogger } from '@mastra/loggers'
38
+ import { Observability, DefaultExporter } from '@mastra/observability'
39
+
40
+ export const mastra = new Mastra({
41
+ logger: new PinoLogger({ name: 'Mastra', level: 'debug' }),
42
+ observability: new Observability({
43
+ configs: {
44
+ default: {
45
+ serviceName: 'my-app',
46
+ exporters: [new DefaultExporter()],
47
+ logging: {
48
+ enabled: true, // set to false to disable log forwarding
49
+ level: 'info', // minimum level: 'debug' | 'info' | 'warn' | 'error' | 'fatal'
50
+ },
51
+ },
52
+ },
53
+ }),
54
+ })
55
+ ```
56
+
57
+ In this example, the console logger outputs all levels starting from `debug`, but only `info` and above are written to observability storage. This keeps your storage clean while still having verbose console output during development.
58
+
59
+ | Option | Type | Default | Description |
60
+ | --------- | ---------- | --------- | ---------------------------------------------------------------------- |
61
+ | `enabled` | `boolean` | `true` | Set to `false` to disable all log forwarding to observability storage. |
62
+ | `level` | `LogLevel` | `'debug'` | Minimum severity level. Logs below this level are discarded. |
63
+
64
+ ### Querying logs
65
+
66
+ Logs written to observability storage are queryable through the Mastra client SDK:
67
+
68
+ ```typescript
69
+ import { MastraClient } from '@mastra/client-js'
70
+
71
+ const client = new MastraClient()
72
+
73
+ const logs = await client.listLogsVNext({
74
+ filters: { level: 'error' },
75
+ pagination: { page: 1, perPage: 50 },
76
+ orderBy: { field: 'timestamp', direction: 'desc' },
77
+ })
78
+ ```
79
+
80
+ When using a persistent storage backend like DuckDB or ClickHouse, logs survive restarts and are available for historical analysis.
81
+
25
82
  ## Customizing logs
26
83
 
27
84
  Mastra provides access to a logger instance via the `mastra.getLogger()` method, available inside both workflow steps and tools. The logger supports standard severity levels: `debug`, `info`, `warn`, and `error`.
28
85
 
29
86
  ### Logging from workflow steps
30
87
 
31
- Within a workflow step, access the logger via the `mastra` parameter inside the `execute` function. This allows you to log messages relevant to the steps execution.
88
+ Within a workflow step, access the logger via the `mastra` parameter inside the `execute` function. This allows you to log messages relevant to the step's execution.
32
89
 
33
90
  ```typescript
34
91
  import { createWorkflow, createStep } from "@mastra/core/workflows";
@@ -52,7 +109,7 @@ export const testWorkflow = createWorkflow({...})
52
109
 
53
110
  ### Logging from tools
54
111
 
55
- Similarly, tools have access to the logger instance via the `mastra` parameter. Use this to log tool specific activity during execution.
112
+ Similarly, tools have access to the logger instance via the `mastra` parameter. Use this to log tool-specific activity during execution.
56
113
 
57
114
  ```typescript
58
115
  import { createTool } from '@mastra/core/tools'
@@ -72,9 +129,7 @@ export const testTool = createTool({
72
129
 
73
130
  ### Logging with additional data
74
131
 
75
- Logger methods accept an optional second argument for additional data. This can be any value, such as an object, string, or number.
76
-
77
- In this example, the log message includes an object with a key of `agent` and a value of the `testAgent` instance.
132
+ Logger methods accept an optional second argument for additional data. Pass a structured object to make logs filterable in observability storage.
78
133
 
79
134
  ```typescript
80
135
  import { createWorkflow, createStep } from "@mastra/core/workflows";
@@ -13,6 +13,10 @@ Specialized tracing for AI operations that captures:
13
13
  - **Workflow steps**: Branching logic, parallel execution, and step outputs
14
14
  - **Automatic instrumentation**: Tracing with decorators
15
15
 
16
+ ### Logging
17
+
18
+ All logger calls from your application and Mastra's internal components are automatically forwarded to observability storage when observability is configured. You can [control the log level and disable forwarding](https://mastra.ai/docs/observability/logging) independently from your console logger.
19
+
16
20
  ## Storage requirements
17
21
 
18
22
  The `DefaultExporter` persists traces to your configured storage backend. Not all storage providers support observability—for the full list, see [Storage Provider Support](https://mastra.ai/docs/observability/tracing/exporters/default).
@@ -56,6 +60,9 @@ export const mastra = new Mastra({
56
60
  new DefaultExporter(), // Persists traces to storage for Mastra Studio
57
61
  new CloudExporter(), // Sends traces to Mastra Cloud (if MASTRA_CLOUD_ACCESS_TOKEN is set)
58
62
  ],
63
+ logging: {
64
+ level: 'info', // Minimum log level forwarded to storage (default: 'debug')
65
+ },
59
66
  spanOutputProcessors: [
60
67
  new SensitiveDataFilter(), // Redacts sensitive data like passwords, tokens, keys
61
68
  ],
@@ -28,6 +28,7 @@ interface ObservabilityInstanceConfig {
28
28
  includeInternalSpans?: boolean
29
29
  requestContextKeys?: string[]
30
30
  serializationOptions?: SerializationOptions
31
+ logging?: { enabled?: boolean; level?: LogLevel }
31
32
  }
32
33
  ```
33
34
 
@@ -55,6 +56,12 @@ interface ObservabilityInstanceConfig {
55
56
 
56
57
  **serializationOptions.maxObjectKeys** (`number`): Maximum number of keys in objects (default: 50)
57
58
 
59
+ **logging** (`{ enabled?: boolean; level?: LogLevel }`): Controls log forwarding to observability storage. See \[Logging to observability storage]\(/docs/observability/logging#logging-to-observability-storage) for details.
60
+
61
+ **logging.enabled** (`boolean`): Set to false to disable log forwarding to observability storage (default: true)
62
+
63
+ **logging.level** (`LogLevel`): Minimum log level to forward. One of 'debug', 'info', 'warn', 'error', 'fatal' (default: 'debug')
64
+
58
65
  ## `SamplingStrategy`
59
66
 
60
67
  ```typescript
@@ -12,6 +12,7 @@ const processor = new LanguageDetector({
12
12
  targetLanguages: ['English', 'en'],
13
13
  threshold: 0.8,
14
14
  strategy: 'translate',
15
+ lastMessageOnly: true,
15
16
  })
16
17
  ```
17
18
 
@@ -31,6 +32,8 @@ const processor = new LanguageDetector({
31
32
 
32
33
  **options.instructions** (`string`): Custom detection instructions for the agent. If not provided, uses default instructions
33
34
 
35
+ **options.lastMessageOnly** (`boolean`): Whether to detect language only for the most recent message in the batch instead of checking every message. Use this to keep LLM calls flat as conversation history grows.
36
+
34
37
  **options.minTextLength** (`number`): Minimum text length to perform detection. Short text is often unreliable for language detection
35
38
 
36
39
  **options.includeDetectionDetails** (`boolean`): Whether to include detailed detection info in logs
@@ -12,6 +12,7 @@ const processor = new ModerationProcessor({
12
12
  threshold: 0.7,
13
13
  strategy: 'block',
14
14
  categories: ['hate', 'harassment', 'violence'],
15
+ lastMessageOnly: true,
15
16
  })
16
17
  ```
17
18
 
@@ -31,6 +32,8 @@ const processor = new ModerationProcessor({
31
32
 
32
33
  **options.includeScores** (`boolean`): Whether to include confidence scores in logs. Useful for tuning thresholds and debugging
33
34
 
35
+ **options.lastMessageOnly** (`boolean`): Whether to run moderation only on the most recent message in the batch instead of checking every message. Use this to avoid an extra LLM call for each earlier message in long conversations.
36
+
34
37
  **options.chunkWindow** (`number`): Number of previous chunks to include for context when moderating stream chunks. If set to 1, includes the previous part, etc.
35
38
 
36
39
  **options.providerOptions** (`ProviderOptions`): Provider-specific options passed to the internal moderation agent. Use this to control model behavior like reasoning effort for thinking models (e.g., \`{ openai: { reasoningEffort: 'low' } }\`)
@@ -12,6 +12,7 @@ const processor = new PIIDetector({
12
12
  threshold: 0.6,
13
13
  strategy: 'redact',
14
14
  detectionTypes: ['email', 'phone', 'credit-card', 'ssn'],
15
+ lastMessageOnly: true,
15
16
  })
16
17
  ```
17
18
 
@@ -33,6 +34,8 @@ const processor = new PIIDetector({
33
34
 
34
35
  **options.includeDetections** (`boolean`): Whether to include detection details in logs. Useful for compliance auditing and debugging
35
36
 
37
+ **options.lastMessageOnly** (`boolean`): Whether to inspect only the most recent message in the batch instead of checking every message. Use this to avoid one LLM call per earlier message in long threads.
38
+
36
39
  **options.preserveFormat** (`boolean`): Whether to preserve PII format during redaction. When true, maintains structure like \*\*\*-\*\*-1234 for phone numbers
37
40
 
38
41
  **options.providerOptions** (`ProviderOptions`): Provider-specific options passed to the internal detection agent. Use this to control model behavior like reasoning effort for thinking models (e.g., \`{ openai: { reasoningEffort: 'low' } }\`)
@@ -12,6 +12,7 @@ const processor = new PromptInjectionDetector({
12
12
  threshold: 0.8,
13
13
  strategy: 'rewrite',
14
14
  detectionTypes: ['injection', 'jailbreak', 'system-override'],
15
+ lastMessageOnly: true,
15
16
  })
16
17
  ```
17
18
 
@@ -31,6 +32,8 @@ const processor = new PromptInjectionDetector({
31
32
 
32
33
  **options.includeScores** (`boolean`): Whether to include confidence scores in logs. Useful for tuning thresholds and debugging
33
34
 
35
+ **options.lastMessageOnly** (`boolean`): Whether to inspect only the most recent message in the batch instead of checking every message. Use this to avoid extra LLM calls for earlier conversation history.
36
+
34
37
  **options.providerOptions** (`ProviderOptions`): Provider-specific options passed to the internal detection agent. Use this to control model behavior like reasoning effort for thinking models (e.g., \`{ openai: { reasoningEffort: 'low' } }\`)
35
38
 
36
39
  ## Returns
@@ -12,6 +12,7 @@ const processor = new SystemPromptScrubber({
12
12
  strategy: 'redact',
13
13
  redactionMethod: 'mask',
14
14
  includeDetections: true,
15
+ lastMessageOnly: true,
15
16
  })
16
17
  ```
17
18
 
@@ -27,6 +28,8 @@ const processor = new SystemPromptScrubber({
27
28
 
28
29
  **options.includeDetections** (`boolean`): Whether to include detection details in warnings. Useful for debugging and monitoring
29
30
 
31
+ **options.lastMessageOnly** (`boolean`): Whether to inspect only the most recent output message in the batch instead of checking every message. Use this to limit LLM-based scrubbing to the latest response.
32
+
30
33
  **options.instructions** (`string`): Custom instructions for the detection agent. If not provided, uses default instructions
31
34
 
32
35
  **options.redactionMethod** (`'mask' | 'placeholder' | 'remove'`): Redaction method for system prompts: 'mask' replaces with asterisks, 'placeholder' replaces with placeholder text, 'remove' removes entirely
package/CHANGELOG.md CHANGED
@@ -1,5 +1,29 @@
1
1
  # @mastra/mcp-docs-server
2
2
 
3
+ ## 1.1.19
4
+
5
+ ### Patch Changes
6
+
7
+ - Standardized all logger calls across the codebase to use static string messages with structured data objects. Dynamic values are now passed as key-value pairs in the second argument instead of being interpolated into template literal strings. This improves log filterability and searchability in observability storage. ([#14899](https://github.com/mastra-ai/mastra/pull/14899))
8
+
9
+ Removed ~150 redundant or noisy log calls including duplicate error logging after trackException and verbose in-memory storage CRUD traces.
10
+
11
+ - Updated dependencies [[`cbeec24`](https://github.com/mastra-ai/mastra/commit/cbeec24b3c97a1a296e7e461e66cc7f7d215dc50), [`cee146b`](https://github.com/mastra-ai/mastra/commit/cee146b5d858212e1df2b2730fc36d3ceda0e08d), [`aa0aeff`](https://github.com/mastra-ai/mastra/commit/aa0aeffa11efbef5e219fbd97bf43d263cfe3afe), [`2bcec65`](https://github.com/mastra-ai/mastra/commit/2bcec652d62b07eab15e9eb9822f70184526eede), [`ad9bded`](https://github.com/mastra-ai/mastra/commit/ad9bdedf86a824801f49928a8d40f6e31ff5450f), [`cbeec24`](https://github.com/mastra-ai/mastra/commit/cbeec24b3c97a1a296e7e461e66cc7f7d215dc50), [`208c0bb`](https://github.com/mastra-ai/mastra/commit/208c0bbacbf5a1da6318f2a0e0c544390e542ddc), [`f566ee7`](https://github.com/mastra-ai/mastra/commit/f566ee7d53a3da33a01103e2a5ac2070ddefe6b0)]:
12
+ - @mastra/core@1.20.0
13
+ - @mastra/mcp@1.4.1
14
+
15
+ ## 1.1.19-alpha.0
16
+
17
+ ### Patch Changes
18
+
19
+ - Standardized all logger calls across the codebase to use static string messages with structured data objects. Dynamic values are now passed as key-value pairs in the second argument instead of being interpolated into template literal strings. This improves log filterability and searchability in observability storage. ([#14899](https://github.com/mastra-ai/mastra/pull/14899))
20
+
21
+ Removed ~150 redundant or noisy log calls including duplicate error logging after trackException and verbose in-memory storage CRUD traces.
22
+
23
+ - Updated dependencies [[`cbeec24`](https://github.com/mastra-ai/mastra/commit/cbeec24b3c97a1a296e7e461e66cc7f7d215dc50), [`cee146b`](https://github.com/mastra-ai/mastra/commit/cee146b5d858212e1df2b2730fc36d3ceda0e08d), [`aa0aeff`](https://github.com/mastra-ai/mastra/commit/aa0aeffa11efbef5e219fbd97bf43d263cfe3afe), [`2bcec65`](https://github.com/mastra-ai/mastra/commit/2bcec652d62b07eab15e9eb9822f70184526eede), [`ad9bded`](https://github.com/mastra-ai/mastra/commit/ad9bdedf86a824801f49928a8d40f6e31ff5450f), [`cbeec24`](https://github.com/mastra-ai/mastra/commit/cbeec24b3c97a1a296e7e461e66cc7f7d215dc50), [`208c0bb`](https://github.com/mastra-ai/mastra/commit/208c0bbacbf5a1da6318f2a0e0c544390e542ddc), [`f566ee7`](https://github.com/mastra-ai/mastra/commit/f566ee7d53a3da33a01103e2a5ac2070ddefe6b0)]:
24
+ - @mastra/core@1.20.0-alpha.0
25
+ - @mastra/mcp@1.4.1-alpha.0
26
+
3
27
  ## 1.1.18
4
28
 
5
29
  ### Patch Changes
package/dist/stdio.js CHANGED
@@ -916,7 +916,7 @@ var clearMastraCourseHistory = {
916
916
  var docsBaseDir = fromPackageRoot(".docs/");
917
917
  async function listDirContents(dirPath) {
918
918
  try {
919
- void logger.debug(`Listing directory contents: ${dirPath}`);
919
+ void logger.debug("Listing directory contents", { path: dirPath });
920
920
  const entries = await fs3.readdir(dirPath, { withFileTypes: true });
921
921
  const dirs = [];
922
922
  const files = [];
@@ -932,17 +932,19 @@ async function listDirContents(dirPath) {
932
932
  files: files.sort()
933
933
  };
934
934
  } catch (error) {
935
- void logger.error(`Failed to list directory contents: ${dirPath}`, error);
935
+ void logger.error("Failed to list directory contents", { path: dirPath, error });
936
936
  throw error;
937
937
  }
938
938
  }
939
939
  async function readDocsContent(docPath, queryKeywords) {
940
- const fullPath = path5__default.resolve(path5__default.join(docsBaseDir, docPath));
941
- if (!fullPath.startsWith(path5__default.resolve(docsBaseDir))) {
942
- void logger.error(`Path traversal attempt detected`);
940
+ const basePath = path5__default.resolve(docsBaseDir);
941
+ const fullPath = path5__default.resolve(path5__default.join(basePath, docPath));
942
+ const relativePath = path5__default.relative(basePath, fullPath);
943
+ if (relativePath.startsWith("..") || path5__default.isAbsolute(relativePath)) {
944
+ void logger.error("Path traversal attempt detected", { path: docPath, resolvedPath: fullPath });
943
945
  return { found: false, isSecurityViolation: true };
944
946
  }
945
- void logger.debug(`Reading docs content from: ${fullPath}`);
947
+ void logger.debug("Reading docs content", { path: fullPath });
946
948
  try {
947
949
  const stats = await fs3.stat(fullPath);
948
950
  if (stats.isDirectory()) {
@@ -987,7 +989,7 @@ async function readDocsContent(docPath, queryKeywords) {
987
989
  }
988
990
  }
989
991
  async function findNearestDirectory(docPath, availablePaths2) {
990
- void logger.debug(`Finding nearest directory for: ${docPath}`);
992
+ void logger.debug("Finding nearest directory", { path: docPath });
991
993
  const parts = docPath.split("/");
992
994
  while (parts.length > 0) {
993
995
  const testPath = parts.join("/");
@@ -1013,7 +1015,7 @@ async function findNearestDirectory(docPath, availablePaths2) {
1013
1015
  return listing.join("\n");
1014
1016
  }
1015
1017
  } catch {
1016
- void logger.debug(`Directory not found, trying parent: ${parts.slice(0, -1).join("/")}`);
1018
+ void logger.debug("Directory not found, trying parent", { parent: parts.slice(0, -1).join("/") });
1017
1019
  }
1018
1020
  parts.pop();
1019
1021
  }
@@ -1833,7 +1835,7 @@ async function discoverMigrations(baseDir, relativePath = "") {
1833
1835
  }
1834
1836
  }
1835
1837
  } catch (error) {
1836
- void logger.error(`Failed to discover migrations in ${fullPath}`, error);
1838
+ void logger.error("Failed to discover migrations", { path: fullPath, error });
1837
1839
  }
1838
1840
  return migrations;
1839
1841
  }
@@ -1906,7 +1908,7 @@ async function readMigrationContent(migrationPath) {
1906
1908
  const content = await fs3.readFile(filePath, "utf-8");
1907
1909
  return content;
1908
1910
  } catch (error) {
1909
- void logger.error(`Failed to read migration: ${migrationPath}`, error);
1911
+ void logger.error("Failed to read migration", { path: migrationPath, error });
1910
1912
  return null;
1911
1913
  }
1912
1914
  }