@mastra/mcp-docs-server 0.0.4-alpha.0 → 0.0.4
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/.docs/organized/changelogs/%40mastra%2Fastra.md +8 -8
- package/.docs/organized/changelogs/%40mastra%2Fchroma.md +8 -8
- package/.docs/organized/changelogs/%40mastra%2Fclient-js.md +8 -8
- package/.docs/organized/changelogs/%40mastra%2Fcomposio.md +8 -8
- package/.docs/organized/changelogs/%40mastra%2Fcore.md +8 -8
- package/.docs/organized/changelogs/%40mastra%2Fdeployer-cloudflare.md +12 -12
- package/.docs/organized/changelogs/%40mastra%2Fdeployer-netlify.md +11 -11
- package/.docs/organized/changelogs/%40mastra%2Fdeployer-vercel.md +11 -11
- package/.docs/organized/changelogs/%40mastra%2Fdeployer.md +10 -10
- package/.docs/organized/changelogs/%40mastra%2Fevals.md +9 -9
- package/.docs/organized/changelogs/%40mastra%2Ffirecrawl.md +16 -16
- package/.docs/organized/changelogs/%40mastra%2Fgithub.md +8 -8
- package/.docs/organized/changelogs/%40mastra%2Floggers.md +8 -8
- package/.docs/organized/changelogs/%40mastra%2Fmcp-docs-server.md +8 -0
- package/.docs/organized/changelogs/%40mastra%2Fmcp.md +9 -9
- package/.docs/organized/changelogs/%40mastra%2Fmemory.md +8 -8
- package/.docs/organized/changelogs/%40mastra%2Fpg.md +8 -8
- package/.docs/organized/changelogs/%40mastra%2Fpinecone.md +8 -8
- package/.docs/organized/changelogs/%40mastra%2Fplayground-ui.md +10 -10
- package/.docs/organized/changelogs/%40mastra%2Fqdrant.md +8 -8
- package/.docs/organized/changelogs/%40mastra%2Frag.md +14 -14
- package/.docs/organized/changelogs/%40mastra%2Fragie.md +8 -8
- package/.docs/organized/changelogs/%40mastra%2Fspeech-azure.md +8 -8
- package/.docs/organized/changelogs/%40mastra%2Fspeech-deepgram.md +8 -8
- package/.docs/organized/changelogs/%40mastra%2Fspeech-elevenlabs.md +8 -8
- package/.docs/organized/changelogs/%40mastra%2Fspeech-google.md +8 -8
- package/.docs/organized/changelogs/%40mastra%2Fspeech-ibm.md +8 -8
- package/.docs/organized/changelogs/%40mastra%2Fspeech-murf.md +8 -8
- package/.docs/organized/changelogs/%40mastra%2Fspeech-openai.md +8 -8
- package/.docs/organized/changelogs/%40mastra%2Fspeech-playai.md +8 -8
- package/.docs/organized/changelogs/%40mastra%2Fspeech-replicate.md +8 -8
- package/.docs/organized/changelogs/%40mastra%2Fspeech-speechify.md +8 -8
- package/.docs/organized/changelogs/%40mastra%2Fstabilityai.md +8 -8
- package/.docs/organized/changelogs/%40mastra%2Fturbopuffer.md +7 -0
- package/.docs/organized/changelogs/%40mastra%2Fupstash.md +12 -12
- package/.docs/organized/changelogs/%40mastra%2Fvectorize.md +12 -12
- package/.docs/organized/changelogs/%40mastra%2Fvoice-azure.md +9 -0
- package/.docs/organized/changelogs/%40mastra%2Fvoice-cloudflare.md +9 -0
- package/.docs/organized/changelogs/%40mastra%2Fvoice-deepgram.md +8 -8
- package/.docs/organized/changelogs/%40mastra%2Fvoice-elevenlabs.md +8 -8
- package/.docs/organized/changelogs/%40mastra%2Fvoice-google.md +8 -8
- package/.docs/organized/changelogs/%40mastra%2Fvoice-murf.md +8 -8
- package/.docs/organized/changelogs/%40mastra%2Fvoice-openai-realtime.md +7 -0
- package/.docs/organized/changelogs/%40mastra%2Fvoice-openai.md +8 -8
- package/.docs/organized/changelogs/%40mastra%2Fvoice-playai.md +8 -8
- package/.docs/organized/changelogs/%40mastra%2Fvoice-sarvam.md +8 -0
- package/.docs/organized/changelogs/%40mastra%2Fvoice-speechify.md +8 -8
- package/.docs/organized/changelogs/create-mastra.md +7 -7
- package/.docs/organized/changelogs/mastra.md +19 -19
- package/.docs/raw/deployment/deployment.mdx +5 -42
- package/.docs/raw/deployment/server.mdx +45 -3
- package/.docs/raw/observability/logging.mdx +38 -0
- package/.docs/raw/observability/nextjs-tracing.mdx +102 -0
- package/.docs/raw/observability/tracing.mdx +110 -0
- package/.docs/raw/reference/client-js/memory.mdx +6 -3
- package/.docs/raw/reference/observability/providers/langsmith.mdx +2 -0
- package/.docs/raw/reference/rag/upstash.mdx +50 -1
- package/.docs/raw/reference/rag/vectorize.mdx +48 -3
- package/.docs/raw/reference/tools/client.mdx +9 -1
- package/.docs/raw/reference/workflows/afterEvent.mdx +76 -0
- package/.docs/raw/reference/workflows/events.mdx +305 -0
- package/.docs/raw/reference/workflows/resumeWithEvent.mdx +134 -0
- package/.docs/raw/reference/workflows/step-retries.mdx +203 -0
- package/.docs/raw/workflows/error-handling.mdx +183 -0
- package/.docs/raw/workflows/suspend-and-resume.mdx +136 -1
- package/dist/_tsup-dts-rollup.d.ts +83 -0
- package/dist/chunk-YEOOTUPA.js +191 -0
- package/dist/prepare-docs/prepare.d.ts +1 -1
- package/dist/prepare-docs/prepare.js +1 -13
- package/dist/stdio.d.ts +0 -1
- package/dist/stdio.js +352 -5
- package/package.json +9 -15
- package/.docs/raw/deployment/logging-and-tracing.mdx +0 -242
- package/dist/index.d.ts +0 -3
- package/dist/index.js +0 -19
- package/dist/prepare-docs/code-examples.d.ts +0 -4
- package/dist/prepare-docs/code-examples.js +0 -91
- package/dist/prepare-docs/copy-raw.d.ts +0 -1
- package/dist/prepare-docs/copy-raw.js +0 -41
- package/dist/prepare-docs/index.d.ts +0 -1
- package/dist/prepare-docs/index.js +0 -8
- package/dist/prepare-docs/package-changes.d.ts +0 -4
- package/dist/prepare-docs/package-changes.js +0 -92
- package/dist/sse.d.ts +0 -1
- package/dist/sse.js +0 -9
- package/dist/tools/__tests__/blog.test.d.ts +0 -1
- package/dist/tools/__tests__/blog.test.js +0 -48
- package/dist/tools/__tests__/changes.test.d.ts +0 -1
- package/dist/tools/__tests__/changes.test.js +0 -37
- package/dist/tools/__tests__/docs.test.d.ts +0 -1
- package/dist/tools/__tests__/docs.test.js +0 -46
- package/dist/tools/__tests__/examples.test.d.ts +0 -1
- package/dist/tools/__tests__/examples.test.js +0 -53
- package/dist/tools/blog.d.ts +0 -15
- package/dist/tools/blog.js +0 -73
- package/dist/tools/changes.d.ts +0 -11
- package/dist/tools/changes.js +0 -69
- package/dist/tools/docs.d.ts +0 -11
- package/dist/tools/docs.js +0 -176
- package/dist/tools/examples.d.ts +0 -11
- package/dist/tools/examples.js +0 -61
- package/dist/utils.d.ts +0 -6
- package/dist/utils.js +0 -9
package/dist/stdio.js
CHANGED
|
@@ -1,9 +1,356 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { prepare } from './
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
import { fromPackageRoot, prepare } from './chunk-YEOOTUPA.js';
|
|
3
|
+
import fs2 from 'node:fs/promises';
|
|
4
|
+
import { FastMCP } from 'tylerbarnes-fastmcp-fix';
|
|
5
|
+
import { JSDOM } from 'jsdom';
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
import path2 from 'node:path';
|
|
8
|
+
|
|
9
|
+
async function fetchBlogPosts() {
|
|
10
|
+
try {
|
|
11
|
+
const response = await fetch("https://mastra.ai/blog");
|
|
12
|
+
if (!response.ok) {
|
|
13
|
+
throw new Error("Failed to fetch blog posts");
|
|
14
|
+
}
|
|
15
|
+
const html = await response.text();
|
|
16
|
+
const dom = new JSDOM(html);
|
|
17
|
+
const document = dom.window.document;
|
|
18
|
+
const blogLinks = Array.from(document.querySelectorAll('a[href^="/blog/"]')).filter((link) => {
|
|
19
|
+
const href = link.getAttribute("href");
|
|
20
|
+
return href !== "/blog" && !href?.includes("authors");
|
|
21
|
+
}).map((link) => {
|
|
22
|
+
const h2 = link.querySelector("h2");
|
|
23
|
+
const title = h2?.textContent?.trim();
|
|
24
|
+
const href = link.getAttribute("href");
|
|
25
|
+
if (title && href) {
|
|
26
|
+
return `[${title}](${href})`;
|
|
27
|
+
}
|
|
28
|
+
return null;
|
|
29
|
+
}).filter(Boolean);
|
|
30
|
+
return "Mastra.ai Blog Posts:\n\n" + blogLinks.join("\n");
|
|
31
|
+
} catch (error) {
|
|
32
|
+
throw new Error("Failed to fetch blog posts " + JSON.stringify(error));
|
|
33
|
+
}
|
|
5
34
|
}
|
|
6
|
-
|
|
35
|
+
async function fetchBlogPost(url) {
|
|
36
|
+
try {
|
|
37
|
+
const response = await fetch(url);
|
|
38
|
+
if (!response.ok) {
|
|
39
|
+
throw new Error("Failed to fetch blog post");
|
|
40
|
+
}
|
|
41
|
+
const html = await response.text();
|
|
42
|
+
const dom = new JSDOM(html);
|
|
43
|
+
const document = dom.window.document;
|
|
44
|
+
const scripts = document.querySelectorAll("script");
|
|
45
|
+
scripts.forEach((script) => script.remove());
|
|
46
|
+
const content = document.body.textContent?.trim() || "";
|
|
47
|
+
if (!content) {
|
|
48
|
+
throw new Error("No content found in blog post");
|
|
49
|
+
}
|
|
50
|
+
return content;
|
|
51
|
+
} catch (error) {
|
|
52
|
+
throw new Error(`Failed to fetch blog post: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
var blogTool = {
|
|
56
|
+
name: "mastraBlog",
|
|
57
|
+
description: "Get Mastra.ai blog content. Without a URL, returns a list of all blog posts. With a URL, returns the specific blog post content in markdown format. The blog contains changelog posts as well as announcements and posts about Mastra features and AI news",
|
|
58
|
+
parameters: z.object({
|
|
59
|
+
url: z.string().describe(
|
|
60
|
+
"URL of a specific blog post to fetch. If the string /blog is passed as the url it returns a list of all blog posts."
|
|
61
|
+
)
|
|
62
|
+
}),
|
|
63
|
+
execute: async (args) => {
|
|
64
|
+
try {
|
|
65
|
+
if (args.url !== `/blog`) {
|
|
66
|
+
return await fetchBlogPost(`https://mastra.ai${args.url}`);
|
|
67
|
+
} else {
|
|
68
|
+
return await fetchBlogPosts();
|
|
69
|
+
}
|
|
70
|
+
} catch (error) {
|
|
71
|
+
if (error instanceof Error) {
|
|
72
|
+
throw new Error("Failed to fetch blog posts");
|
|
73
|
+
}
|
|
74
|
+
throw error;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
function encodePackageName(name) {
|
|
79
|
+
return encodeURIComponent(name);
|
|
80
|
+
}
|
|
81
|
+
function decodePackageName(name) {
|
|
82
|
+
return decodeURIComponent(name);
|
|
83
|
+
}
|
|
84
|
+
var changelogsDir = fromPackageRoot(".docs/organized/changelogs");
|
|
85
|
+
async function listPackageChangelogs() {
|
|
86
|
+
try {
|
|
87
|
+
const files = await fs2.readdir(changelogsDir);
|
|
88
|
+
return files.filter((f) => f.endsWith(".md")).map((f) => ({
|
|
89
|
+
name: decodePackageName(f.replace(".md", "")),
|
|
90
|
+
path: f
|
|
91
|
+
})).sort((a, b) => a.name.localeCompare(b.name));
|
|
92
|
+
} catch {
|
|
93
|
+
return [];
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
async function readPackageChangelog(filename) {
|
|
97
|
+
const encodedName = encodePackageName(filename.replace(".md", ""));
|
|
98
|
+
const filePath = path2.join(changelogsDir, `${encodedName}.md`);
|
|
99
|
+
try {
|
|
100
|
+
return await fs2.readFile(filePath, "utf-8");
|
|
101
|
+
} catch {
|
|
102
|
+
const packages = await listPackageChangelogs();
|
|
103
|
+
const availablePackages = packages.map((pkg) => `- ${pkg.name}`).join("\n");
|
|
104
|
+
throw new Error(
|
|
105
|
+
`Changelog for "${filename.replace(".md", "")}" not found.
|
|
106
|
+
|
|
107
|
+
Available packages:
|
|
108
|
+
${availablePackages}`
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
var initialPackages = await listPackageChangelogs();
|
|
113
|
+
var packagesListing = initialPackages.length > 0 ? "\n\nAvailable packages: " + initialPackages.map((pkg) => pkg.name).join(", ") : "\n\nNo package changelogs available yet. Run the documentation preparation script first.";
|
|
114
|
+
var changesSchema = z.object({
|
|
115
|
+
package: z.string().optional().describe("Name of the specific package to fetch changelog for. If not provided, lists all available packages.")
|
|
116
|
+
});
|
|
117
|
+
var changesTool = {
|
|
118
|
+
name: "mastraChanges",
|
|
119
|
+
description: "Get changelog information for Mastra.ai packages. " + packagesListing,
|
|
120
|
+
parameters: changesSchema,
|
|
121
|
+
execute: async (args, _context) => {
|
|
122
|
+
if (!args.package) {
|
|
123
|
+
const packages = await listPackageChangelogs();
|
|
124
|
+
return ["Available package changelogs:", "", ...packages.map((pkg) => `- ${pkg.name}`)].join("\n");
|
|
125
|
+
}
|
|
126
|
+
const content = await readPackageChangelog(args.package);
|
|
127
|
+
return content;
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
var docsBaseDir = fromPackageRoot(".docs/raw/");
|
|
131
|
+
async function listDirContents(dirPath) {
|
|
132
|
+
const entries = await fs2.readdir(dirPath, { withFileTypes: true });
|
|
133
|
+
const dirs = [];
|
|
134
|
+
const files = [];
|
|
135
|
+
for (const entry of entries) {
|
|
136
|
+
if (entry.isDirectory()) {
|
|
137
|
+
dirs.push(entry.name + "/");
|
|
138
|
+
} else if (entry.isFile() && entry.name.endsWith(".mdx")) {
|
|
139
|
+
files.push(entry.name);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return {
|
|
143
|
+
dirs: dirs.sort(),
|
|
144
|
+
files: files.sort()
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
async function readMdxContent(docPath) {
|
|
148
|
+
const fullPath = path2.join(docsBaseDir, docPath);
|
|
149
|
+
try {
|
|
150
|
+
const stats = await fs2.stat(fullPath);
|
|
151
|
+
if (stats.isDirectory()) {
|
|
152
|
+
const { dirs, files } = await listDirContents(fullPath);
|
|
153
|
+
const dirListing = [
|
|
154
|
+
`Directory contents of ${docPath}:`,
|
|
155
|
+
"",
|
|
156
|
+
dirs.length > 0 ? "Subdirectories:" : "No subdirectories.",
|
|
157
|
+
...dirs.map((d) => `- ${d}`),
|
|
158
|
+
"",
|
|
159
|
+
files.length > 0 ? "Files in this directory:" : "No files in this directory.",
|
|
160
|
+
...files.map((f) => `- ${f}`),
|
|
161
|
+
"",
|
|
162
|
+
"---",
|
|
163
|
+
"",
|
|
164
|
+
"Contents of all files in this directory:",
|
|
165
|
+
""
|
|
166
|
+
].join("\n");
|
|
167
|
+
let fileContents = "";
|
|
168
|
+
for (const file of files) {
|
|
169
|
+
const filePath = path2.join(fullPath, file);
|
|
170
|
+
const content = await fs2.readFile(filePath, "utf-8");
|
|
171
|
+
fileContents += `
|
|
172
|
+
|
|
173
|
+
# ${file}
|
|
174
|
+
|
|
175
|
+
${content}`;
|
|
176
|
+
}
|
|
177
|
+
return dirListing + fileContents;
|
|
178
|
+
}
|
|
179
|
+
return fs2.readFile(fullPath, "utf-8");
|
|
180
|
+
} catch (error) {
|
|
181
|
+
throw new Error(`Path not found: ${docPath}`);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
async function findNearestDirectory(docPath, availablePaths2) {
|
|
185
|
+
const parts = docPath.split("/");
|
|
186
|
+
while (parts.length > 0) {
|
|
187
|
+
const testPath = parts.join("/");
|
|
188
|
+
try {
|
|
189
|
+
const fullPath = path2.join(docsBaseDir, testPath);
|
|
190
|
+
const stats = await fs2.stat(fullPath);
|
|
191
|
+
if (stats.isDirectory()) {
|
|
192
|
+
const { dirs, files } = await listDirContents(fullPath);
|
|
193
|
+
return [
|
|
194
|
+
`Path "${docPath}" not found.`,
|
|
195
|
+
`Here are the available paths in "${testPath}":`,
|
|
196
|
+
"",
|
|
197
|
+
dirs.length > 0 ? "Directories:" : "No subdirectories.",
|
|
198
|
+
...dirs.map((d) => `- ${testPath}/${d}`),
|
|
199
|
+
"",
|
|
200
|
+
files.length > 0 ? "Files:" : "No files.",
|
|
201
|
+
...files.map((f) => `- ${testPath}/${f}`)
|
|
202
|
+
].join("\n");
|
|
203
|
+
}
|
|
204
|
+
} catch {
|
|
205
|
+
}
|
|
206
|
+
parts.pop();
|
|
207
|
+
}
|
|
208
|
+
return [`Path "${docPath}" not found.`, "Here are all available paths:", "", availablePaths2].join("\n");
|
|
209
|
+
}
|
|
210
|
+
async function getAvailablePaths() {
|
|
211
|
+
const { dirs, files } = await listDirContents(docsBaseDir);
|
|
212
|
+
let referenceDirs = [];
|
|
213
|
+
if (dirs.includes("reference/")) {
|
|
214
|
+
const { dirs: refDirs } = await listDirContents(path2.join(docsBaseDir, "reference"));
|
|
215
|
+
referenceDirs = refDirs.map((d) => `reference/${d}`);
|
|
216
|
+
}
|
|
217
|
+
return [
|
|
218
|
+
"Available top-level paths:",
|
|
219
|
+
"",
|
|
220
|
+
"Directories:",
|
|
221
|
+
...dirs.map((d) => `- ${d}`),
|
|
222
|
+
"",
|
|
223
|
+
referenceDirs.length > 0 ? "Reference subdirectories:" : "",
|
|
224
|
+
...referenceDirs.map((d) => `- ${d}`),
|
|
225
|
+
"",
|
|
226
|
+
"Files:",
|
|
227
|
+
...files.map((f) => `- ${f}`)
|
|
228
|
+
].filter(Boolean).join("\n");
|
|
229
|
+
}
|
|
230
|
+
var availablePaths = await getAvailablePaths();
|
|
231
|
+
var docsSchema = z.object({
|
|
232
|
+
paths: z.array(z.string()).min(1).describe(`One or more documentation paths to fetch
|
|
233
|
+
Available paths:
|
|
234
|
+
${availablePaths}`)
|
|
235
|
+
});
|
|
236
|
+
var docsTool = {
|
|
237
|
+
name: "mastraDocs",
|
|
238
|
+
description: "Get Mastra.ai documentation. Request paths to explore the docs. References contain API docs. Other paths contain guides. The user doesn't know about files and directories. This is your internal knowledge the user can't read. If the user asks about a feature check general docs as well as reference docs for that feature. Ex: with evals check in evals/ and in reference/evals/. Provide code examples so the user understands. If you build a URL from the path, only paths ending in .mdx exist. Note that docs about MCP are currently in reference/tools/. IMPORTANT: Be concise with your answers. The user will ask for more info. If packages need to be installed, provide the pnpm command to install them. Ex. if you see `import { X } from \"@mastra/$PACKAGE_NAME\"` in an example, show an install command. Always install latest tag, not alpha unless requested. If you scaffold a new project it may be in a subdir",
|
|
239
|
+
parameters: docsSchema,
|
|
240
|
+
execute: async (args, _context) => {
|
|
241
|
+
try {
|
|
242
|
+
const results = await Promise.all(
|
|
243
|
+
args.paths.map(async (path4) => {
|
|
244
|
+
try {
|
|
245
|
+
const content = await readMdxContent(path4);
|
|
246
|
+
return {
|
|
247
|
+
path: path4,
|
|
248
|
+
content,
|
|
249
|
+
error: null
|
|
250
|
+
};
|
|
251
|
+
} catch (error) {
|
|
252
|
+
if (error instanceof Error && error.message.includes("Path not found")) {
|
|
253
|
+
const suggestions = await findNearestDirectory(path4, availablePaths);
|
|
254
|
+
return {
|
|
255
|
+
path: path4,
|
|
256
|
+
content: null,
|
|
257
|
+
error: suggestions
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
return {
|
|
261
|
+
path: path4,
|
|
262
|
+
content: null,
|
|
263
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
})
|
|
267
|
+
);
|
|
268
|
+
const output = results.map((result) => {
|
|
269
|
+
if (result.error) {
|
|
270
|
+
return `## ${result.path}
|
|
271
|
+
|
|
272
|
+
${result.error}
|
|
273
|
+
|
|
274
|
+
---
|
|
275
|
+
`;
|
|
276
|
+
}
|
|
277
|
+
return `## ${result.path}
|
|
278
|
+
|
|
279
|
+
${result.content}
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
`;
|
|
283
|
+
}).join("\n");
|
|
284
|
+
return output;
|
|
285
|
+
} catch (error) {
|
|
286
|
+
if (error instanceof Error) {
|
|
287
|
+
throw new Error(`Failed to fetch documentation: ${error.message}`);
|
|
288
|
+
}
|
|
289
|
+
throw error;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
};
|
|
293
|
+
var examplesDir = fromPackageRoot(".docs/organized/code-examples");
|
|
294
|
+
async function listCodeExamples() {
|
|
295
|
+
try {
|
|
296
|
+
const files = await fs2.readdir(examplesDir);
|
|
297
|
+
return files.filter((f) => f.endsWith(".md")).map((f) => ({
|
|
298
|
+
name: f.replace(".md", ""),
|
|
299
|
+
path: f
|
|
300
|
+
})).sort((a, b) => a.name.localeCompare(b.name));
|
|
301
|
+
} catch {
|
|
302
|
+
return [];
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
async function readCodeExample(filename) {
|
|
306
|
+
const filePath = path2.join(examplesDir, filename);
|
|
307
|
+
try {
|
|
308
|
+
return await fs2.readFile(filePath, "utf-8");
|
|
309
|
+
} catch {
|
|
310
|
+
const examples = await listCodeExamples();
|
|
311
|
+
const availableExamples = examples.map((ex) => `- ${ex.name}`).join("\n");
|
|
312
|
+
throw new Error(`Example "${filename}" not found.
|
|
313
|
+
|
|
314
|
+
Available examples:
|
|
315
|
+
${availableExamples}`);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
var initialExamples = await listCodeExamples();
|
|
319
|
+
var examplesListing = initialExamples.length > 0 ? "\n\nAvailable examples: " + initialExamples.map((ex) => ex.name).join(", ") : "\n\nNo examples available yet. Run the documentation preparation script first.";
|
|
320
|
+
var examplesSchema = z.object({
|
|
321
|
+
example: z.string().optional().describe(
|
|
322
|
+
"Name of the specific example to fetch. If not provided, lists all available examples." + examplesListing
|
|
323
|
+
)
|
|
324
|
+
});
|
|
325
|
+
var examplesTool = {
|
|
326
|
+
name: "mastraExamples",
|
|
327
|
+
description: "Get code examples from the Mastra.ai examples directory. Without a specific example name, lists all available examples. With an example name, returns the full source code of that example.",
|
|
328
|
+
parameters: examplesSchema,
|
|
329
|
+
execute: async (args, _context) => {
|
|
330
|
+
if (!args.example) {
|
|
331
|
+
const examples = await listCodeExamples();
|
|
332
|
+
return ["Available code examples:", "", ...examples.map((ex) => `- ${ex.name}`)].join("\n");
|
|
333
|
+
}
|
|
334
|
+
const filename = args.example.endsWith(".md") ? args.example : `${args.example}.md`;
|
|
335
|
+
const content = await readCodeExample(filename);
|
|
336
|
+
return content;
|
|
337
|
+
}
|
|
338
|
+
};
|
|
339
|
+
|
|
340
|
+
// src/index.ts
|
|
341
|
+
if (process.env.REBUILD_DOCS_ON_START === "true") {
|
|
342
|
+
await prepare();
|
|
343
|
+
}
|
|
344
|
+
var server = new FastMCP({
|
|
345
|
+
name: "Mastra Documentation Server",
|
|
346
|
+
version: JSON.parse(await fs2.readFile(fromPackageRoot(`package.json`), "utf8")).version
|
|
347
|
+
});
|
|
348
|
+
server.addTool(blogTool);
|
|
349
|
+
server.addTool(docsTool);
|
|
350
|
+
server.addTool(examplesTool);
|
|
351
|
+
server.addTool(changesTool);
|
|
352
|
+
|
|
353
|
+
// src/stdio.ts
|
|
7
354
|
void server.start({
|
|
8
|
-
|
|
355
|
+
transportType: "stdio"
|
|
9
356
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mastra/mcp-docs-server",
|
|
3
|
-
"version": "0.0.4
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"description": "MCP server for accessing Mastra.ai documentation, changelogs, and news.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -16,10 +16,6 @@
|
|
|
16
16
|
"import": {
|
|
17
17
|
"types": "./dist/index.d.ts",
|
|
18
18
|
"default": "./dist/index.js"
|
|
19
|
-
},
|
|
20
|
-
"require": {
|
|
21
|
-
"types": "./dist/index.d.cts",
|
|
22
|
-
"default": "./dist/index.cjs"
|
|
23
19
|
}
|
|
24
20
|
},
|
|
25
21
|
"./package.json": "./package.json"
|
|
@@ -37,29 +33,27 @@
|
|
|
37
33
|
"tylerbarnes-fastmcp-fix": "^1.0.0",
|
|
38
34
|
"uuid": "^11.1.0",
|
|
39
35
|
"zod": "^3.22.4",
|
|
40
|
-
"@mastra/core": "^0.6.4
|
|
36
|
+
"@mastra/core": "^0.6.4"
|
|
41
37
|
},
|
|
42
38
|
"devDependencies": {
|
|
39
|
+
"@hono/node-server": "^1.13.8",
|
|
43
40
|
"@types/jsdom": "^21.1.7",
|
|
44
41
|
"@types/node": "^20.11.24",
|
|
45
42
|
"@types/turndown": "^5.0.5",
|
|
46
43
|
"@wong2/mcp-cli": "^1.6.0",
|
|
47
44
|
"eslint": "^9.22.0",
|
|
45
|
+
"hono": "^4.7.4",
|
|
48
46
|
"tsup": "^8.4.0",
|
|
49
47
|
"tsx": "^4.7.1",
|
|
50
48
|
"typescript": "^5.3.3",
|
|
51
49
|
"vitest": "^3.0.8",
|
|
52
|
-
"@internal/lint": "0.0.1"
|
|
50
|
+
"@internal/lint": "0.0.1",
|
|
51
|
+
"@mastra/mcp": "^0.3.5"
|
|
53
52
|
},
|
|
54
53
|
"scripts": {
|
|
55
|
-
"prepare-docs": "
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
"predev": "pnpm prepare-docs",
|
|
59
|
-
"dev": "fastmcp dev src/index.ts",
|
|
60
|
-
"inspect": "fastmcp inspect src/index.ts",
|
|
61
|
-
"build:watch": "pnpm build --watch",
|
|
62
|
-
"pretest": "pnpm build",
|
|
54
|
+
"prepare-docs": "PREPARE=true node dist/prepare-docs/prepare.js",
|
|
55
|
+
"build:cli": "tsup src/stdio.ts src/prepare-docs/prepare.ts --format esm --experimental-dts --treeshake=smallest --splitting",
|
|
56
|
+
"pretest": "pnpm turbo build --filter @mastra/mcp-docs-server",
|
|
63
57
|
"test": "vitest run",
|
|
64
58
|
"lint": "eslint ."
|
|
65
59
|
}
|
|
@@ -1,242 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: "Logging and Tracing | Mastra Deployment Documentation"
|
|
3
|
-
description: Documentation on effective logging and tracing in Mastra, crucial for understanding application behavior and improving AI accuracy.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
import Image from "next/image";
|
|
7
|
-
|
|
8
|
-
# Logging and Tracing
|
|
9
|
-
|
|
10
|
-
Effective logging and tracing are crucial for understanding the behavior of your application.
|
|
11
|
-
|
|
12
|
-
Tracing is especially important for AI engineering. Teams building AI products find that visibility into inputs and outputs of every step of every run is crucial to improving accuracy. You get this with Mastra's telemetry.
|
|
13
|
-
|
|
14
|
-
## Logging
|
|
15
|
-
|
|
16
|
-
In Mastra, logs can detail when certain functions run, what input data they receive, and how they respond.
|
|
17
|
-
|
|
18
|
-
### Basic Setup
|
|
19
|
-
|
|
20
|
-
Here's a minimal example that sets up a **console logger** at the `INFO` level. This will print out informational messages and above (i.e., `INFO`, `WARN`, `ERROR`) to the console.
|
|
21
|
-
|
|
22
|
-
```typescript filename="mastra.config.ts" showLineNumbers copy
|
|
23
|
-
import { Mastra } from "@mastra/core";
|
|
24
|
-
import { createLogger } from "@mastra/core/logger";
|
|
25
|
-
|
|
26
|
-
export const mastra = new Mastra({
|
|
27
|
-
// Other Mastra configuration...
|
|
28
|
-
logger: createLogger({
|
|
29
|
-
name: "Mastra",
|
|
30
|
-
level: "info",
|
|
31
|
-
}),
|
|
32
|
-
});
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
In this configuration:
|
|
36
|
-
|
|
37
|
-
- `name: "Mastra"` specifies the name to group logs under.
|
|
38
|
-
- `level: "info"` sets the minimum severity of logs to record.
|
|
39
|
-
|
|
40
|
-
### Configuration
|
|
41
|
-
|
|
42
|
-
- For more details on the options you can pass to `createLogger()`, see the [createLogger reference documentation](/docs/reference/observability/create-logger.mdx).
|
|
43
|
-
- Once you have a `Logger` instance, you can call its methods (e.g., `.info()`, `.warn()`, `.error()`) in the [Logger instance reference documentation](/docs/reference/observability/logger.mdx).
|
|
44
|
-
- If you want to send your logs to an external service for centralized collection, analysis, or storage, you can configure other logger types such as Upstash Redis. Consult the [createLogger reference documentation](/docs/reference/observability/create-logger.mdx) for details on parameters like `url`, `token`, and `key` when using the `UPSTASH` logger type.
|
|
45
|
-
|
|
46
|
-
## Telemetry
|
|
47
|
-
|
|
48
|
-
Mastra supports the OpenTelemetry Protocol (OTLP) for tracing and monitoring your application. When telemetry is enabled, Mastra automatically traces all core primitives including agent operations, LLM interactions, tool executions, integration calls, workflow runs, and database operations. Your telemetry data can then be exported to any OTEL collector.
|
|
49
|
-
|
|
50
|
-
### Basic Configuration
|
|
51
|
-
|
|
52
|
-
Here's a simple example of enabling telemetry:
|
|
53
|
-
|
|
54
|
-
```ts filename="mastra.config.ts" showLineNumbers copy
|
|
55
|
-
export const mastra = new Mastra({
|
|
56
|
-
// ... other config
|
|
57
|
-
telemetry: {
|
|
58
|
-
serviceName: "my-app",
|
|
59
|
-
enabled: true,
|
|
60
|
-
sampling: {
|
|
61
|
-
type: "always_on",
|
|
62
|
-
},
|
|
63
|
-
export: {
|
|
64
|
-
type: "otlp",
|
|
65
|
-
endpoint: "http://localhost:4318", // SigNoz local endpoint
|
|
66
|
-
},
|
|
67
|
-
},
|
|
68
|
-
});
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
### Configuration Options
|
|
72
|
-
|
|
73
|
-
The telemetry config accepts these properties:
|
|
74
|
-
|
|
75
|
-
```ts
|
|
76
|
-
type OtelConfig = {
|
|
77
|
-
// Name to identify your service in traces (optional)
|
|
78
|
-
serviceName?: string;
|
|
79
|
-
|
|
80
|
-
// Enable/disable telemetry (defaults to true)
|
|
81
|
-
enabled?: boolean;
|
|
82
|
-
|
|
83
|
-
// Control how many traces are sampled
|
|
84
|
-
sampling?: {
|
|
85
|
-
type: "ratio" | "always_on" | "always_off" | "parent_based";
|
|
86
|
-
probability?: number; // For ratio sampling
|
|
87
|
-
root?: {
|
|
88
|
-
probability: number; // For parent_based sampling
|
|
89
|
-
};
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
// Where to send telemetry data
|
|
93
|
-
export?: {
|
|
94
|
-
type: "otlp" | "console";
|
|
95
|
-
endpoint?: string;
|
|
96
|
-
headers?: Record<string, string>;
|
|
97
|
-
};
|
|
98
|
-
};
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
See the [OtelConfig reference documentation](/docs/reference/observability/otel-config.mdx) for more details.
|
|
102
|
-
|
|
103
|
-
### Environment Variables
|
|
104
|
-
|
|
105
|
-
You can configure the OTLP endpoint and headers through environment variables:
|
|
106
|
-
|
|
107
|
-
```env filename=".env" copy
|
|
108
|
-
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
|
|
109
|
-
OTEL_EXPORTER_OTLP_HEADERS=x-api-key=your-api-key
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
Then in your config:
|
|
113
|
-
|
|
114
|
-
```ts filename="mastra.config.ts" showLineNumbers copy
|
|
115
|
-
export const mastra = new Mastra({
|
|
116
|
-
// ... other config
|
|
117
|
-
telemetry: {
|
|
118
|
-
serviceName: "my-app",
|
|
119
|
-
enabled: true,
|
|
120
|
-
export: {
|
|
121
|
-
type: "otlp",
|
|
122
|
-
// endpoint and headers will be picked up from env vars
|
|
123
|
-
},
|
|
124
|
-
},
|
|
125
|
-
});
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
### Example: SigNoz Integration
|
|
129
|
-
|
|
130
|
-
Here's what a traced agent interaction looks like in [SigNoz](https://signoz.io):
|
|
131
|
-
|
|
132
|
-
<img
|
|
133
|
-
src="/docs/signoz-telemetry-demo.png"
|
|
134
|
-
alt="Agent interaction trace showing spans, LLM calls, and tool executions"
|
|
135
|
-
style={{ maxWidth: "800px", width: "100%", margin: "8px 0" }}
|
|
136
|
-
className="nextra-image rounded-md"
|
|
137
|
-
data-zoom
|
|
138
|
-
width={800}
|
|
139
|
-
height={400}
|
|
140
|
-
/>
|
|
141
|
-
|
|
142
|
-
### Other Supported Providers
|
|
143
|
-
|
|
144
|
-
For a complete list of supported observability providers and their configuration details, see the [Observability Providers reference](../reference/observability/providers/).
|
|
145
|
-
|
|
146
|
-
## Next.js Configuration
|
|
147
|
-
|
|
148
|
-
If you're using Next.js, you have two options for setting up OpenTelemetry instrumentation:
|
|
149
|
-
|
|
150
|
-
#### Option 1: Using Vercel's OTEL Setup
|
|
151
|
-
|
|
152
|
-
If you're deploying to Vercel, you can use their built-in OpenTelemetry setup:
|
|
153
|
-
|
|
154
|
-
1. Install the required dependencies:
|
|
155
|
-
|
|
156
|
-
```bash copy
|
|
157
|
-
npm install @opentelemetry/api @vercel/otel
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
2. Create an instrumentation file at the root of your project (or in the src folder if using one):
|
|
161
|
-
|
|
162
|
-
```ts filename="instrumentation.ts" copy
|
|
163
|
-
import { registerOTel } from '@vercel/otel'
|
|
164
|
-
|
|
165
|
-
export function register() {
|
|
166
|
-
registerOTel({ serviceName: 'your-project-name' })
|
|
167
|
-
}
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
#### Option 2: Using Custom Exporters
|
|
171
|
-
|
|
172
|
-
If you're using other observability tools (like Langfuse), you can configure a custom exporter:
|
|
173
|
-
|
|
174
|
-
1. Install the required dependencies (example using Langfuse):
|
|
175
|
-
|
|
176
|
-
```bash copy
|
|
177
|
-
npm install @opentelemetry/api langfuse-vercel
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
2. Create an instrumentation file:
|
|
181
|
-
|
|
182
|
-
```ts filename="instrumentation.ts" copy
|
|
183
|
-
import {
|
|
184
|
-
NodeSDK,
|
|
185
|
-
ATTR_SERVICE_NAME,
|
|
186
|
-
Resource,
|
|
187
|
-
} from '@mastra/core/telemetry/otel-vendor';
|
|
188
|
-
import { LangfuseExporter } from 'langfuse-vercel';
|
|
189
|
-
|
|
190
|
-
export function register() {
|
|
191
|
-
const exporter = new LangfuseExporter({
|
|
192
|
-
// ... Langfuse config
|
|
193
|
-
})
|
|
194
|
-
|
|
195
|
-
const sdk = new NodeSDK({
|
|
196
|
-
resource: new Resource({
|
|
197
|
-
[ATTR_SERVICE_NAME]: 'ai',
|
|
198
|
-
}),
|
|
199
|
-
traceExporter: exporter,
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
sdk.start();
|
|
203
|
-
}
|
|
204
|
-
```
|
|
205
|
-
|
|
206
|
-
#### Next.js Configuration
|
|
207
|
-
|
|
208
|
-
For either option, enable the instrumentation hook in your Next.js config:
|
|
209
|
-
|
|
210
|
-
```ts filename="next.config.ts" showLineNumbers copy
|
|
211
|
-
import type { NextConfig } from "next";
|
|
212
|
-
|
|
213
|
-
const nextConfig: NextConfig = {
|
|
214
|
-
experimental: {
|
|
215
|
-
instrumentationHook: true // Not required in Next.js 15+
|
|
216
|
-
}
|
|
217
|
-
};
|
|
218
|
-
|
|
219
|
-
export default nextConfig;
|
|
220
|
-
```
|
|
221
|
-
|
|
222
|
-
#### Mastra Configuration
|
|
223
|
-
|
|
224
|
-
Configure your Mastra instance:
|
|
225
|
-
|
|
226
|
-
```typescript filename="mastra.config.ts" copy
|
|
227
|
-
import { Mastra } from "@mastra/core";
|
|
228
|
-
|
|
229
|
-
export const mastra = new Mastra({
|
|
230
|
-
// ... other config
|
|
231
|
-
telemetry: {
|
|
232
|
-
serviceName: "your-project-name",
|
|
233
|
-
enabled: true
|
|
234
|
-
}
|
|
235
|
-
});
|
|
236
|
-
```
|
|
237
|
-
|
|
238
|
-
This setup will enable OpenTelemetry tracing for your Next.js application and Mastra operations.
|
|
239
|
-
|
|
240
|
-
For more details, see the documentation for:
|
|
241
|
-
- [Next.js Instrumentation](https://nextjs.org/docs/app/building-your-application/optimizing/instrumentation)
|
|
242
|
-
- [Vercel OpenTelemetry](https://vercel.com/docs/observability/otel-overview/quickstart)
|
package/dist/index.d.ts
DELETED
package/dist/index.js
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import fs from 'node:fs/promises';
|
|
2
|
-
import { FastMCP } from 'tylerbarnes-fastmcp-fix';
|
|
3
|
-
import { blogTool } from './tools/blog.js';
|
|
4
|
-
import { changesTool } from './tools/changes.js';
|
|
5
|
-
import { docsTool } from './tools/docs.js';
|
|
6
|
-
import { examplesTool } from './tools/examples.js';
|
|
7
|
-
import { fromPackageRoot } from './utils.js';
|
|
8
|
-
// console.error('Starting Mastra Documentation Server...');
|
|
9
|
-
// console.error('Docs base dir:', path.join(__dirname, '../.docs/raw/'));
|
|
10
|
-
const server = new FastMCP({
|
|
11
|
-
name: 'Mastra Documentation Server',
|
|
12
|
-
version: JSON.parse(await fs.readFile(fromPackageRoot(`package.json`), 'utf8')).version,
|
|
13
|
-
});
|
|
14
|
-
// Add tools
|
|
15
|
-
server.addTool(blogTool);
|
|
16
|
-
server.addTool(docsTool);
|
|
17
|
-
server.addTool(examplesTool);
|
|
18
|
-
server.addTool(changesTool);
|
|
19
|
-
export { server };
|