Analyze Note Tags
tags.analyzeAnalyze a single note to extract and categorize its tags into frontmatter, inline, and deduplicated union lists.
Instructions
Return the tags present in a single note, split into frontmatterTags, inlineTags, and their de-duplicated union allTags. Use this when you have one note and want to know what tags it carries — contrast with tags.search, which scans the whole vault for one specific tag. Read-only.
Operates on the session-active vault (see vault.current — selectable via vault.select) unless an explicit vaultPath argument is passed, which always wins.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Vault-relative note path to analyze. | |
| vaultPath | No |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | ||
| frontmatterTags | Yes | ||
| inlineTags | Yes | ||
| allTags | Yes | Union of frontmatter and inline tags, de-duplicated. |
Implementation Reference
- src/server/tools/tags.ts:74-87 (handler)The handler registration for the 'tags.analyze' tool. It parses args using tagsAnalyzeArgsSchema, reads the note via readNote(), and extracts tags via extractAllTags().
{ name: "tags.analyze", title: "Analyze Note Tags", description: "Return the tags present in a single note, split into `frontmatterTags`, `inlineTags`, and their de-duplicated union `allTags`. Use this when you have one note and want to know what tags it carries — contrast with `tags.search`, which scans the whole vault for one specific tag. Read-only.", inputSchema: tagsAnalyzeArgsSchema, outputSchema: tagsAnalyzeOutputSchema, annotations: READ_ONLY, handler: async (context, rawArgs) => { const args = tagsAnalyzeArgsSchema.parse(rawArgs) as TagsAnalyzeArgs; const note = await readNote(context, { path: args.path, vaultPath: args.vaultPath }); return { path: note.path, ...extractAllTags(note.content) }; }, }, - src/schema/tags.ts:39-46 (schema)Input schema (tagsAnalyzeArgsSchema) defining the 'path' and optional 'vaultPath' arguments accepted by tags.analyze.
export const tagsAnalyzeArgsSchema = z .object({ path: notePathSchema.describe("Vault-relative note path to analyze."), vaultPath: z.string().optional(), }) .strict() .describe("Arguments for `tags.analyze`."); export type TagsAnalyzeArgs = z.input<typeof tagsAnalyzeArgsSchema>; - src/schema/tags.ts:98-105 (schema)Output schema (tagsAnalyzeOutputSchema) defining the shape returned by tags.analyze: path, frontmatterTags, inlineTags, and allTags.
export const tagsAnalyzeOutputSchema = z .object({ path: z.string(), frontmatterTags: z.array(z.string()), inlineTags: z.array(z.string()), allTags: z.array(z.string()).describe("Union of frontmatter and inline tags, de-duplicated."), }) .passthrough(); - src/server/tools/tags.ts:60-101 (registration)The tags.analyze tool is registered as part of the tagTools array (line 61-101 contains the full tags.search, tags.analyze, and tags.list registrations).
}, { name: "tags.search", title: "Search Notes By Tag", description: "Find every note in the vault that contains a given tag, either in frontmatter `tags` or as an inline `#tag` in the body. Leading `#` on the query is stripped. For each hit, the result carries `{file, absolutePath, tagLocations: {frontmatter, inline}}` so callers can distinguish where the tag came from. Read-only. For analyzing tags of ONE specific note (not a vault-wide search), use `tags.analyze` instead.", inputSchema: tagsSearchArgsSchema, outputSchema: tagsSearchOutputSchema, annotations: READ_ONLY, handler: async (context, rawArgs) => { const args = tagsSearchArgsSchema.parse(rawArgs) as TagsSearchArgs; return searchByTag(context, args); }, }, { name: "tags.analyze", title: "Analyze Note Tags", description: "Return the tags present in a single note, split into `frontmatterTags`, `inlineTags`, and their de-duplicated union `allTags`. Use this when you have one note and want to know what tags it carries — contrast with `tags.search`, which scans the whole vault for one specific tag. Read-only.", inputSchema: tagsAnalyzeArgsSchema, outputSchema: tagsAnalyzeOutputSchema, annotations: READ_ONLY, handler: async (context, rawArgs) => { const args = tagsAnalyzeArgsSchema.parse(rawArgs) as TagsAnalyzeArgs; const note = await readNote(context, { path: args.path, vaultPath: args.vaultPath }); return { path: note.path, ...extractAllTags(note.content) }; }, }, { name: "tags.list", title: "List All Tags", description: "List every unique tag used across the vault (frontmatter and inline combined). With `includeCounts: true`, each item includes how many notes carry the tag; `sortBy` lets you sort by `name` or `count` (the latter requires counts). Read-only. For finding notes carrying a specific tag, use `tags.search`.", inputSchema: tagsListArgsSchema, outputSchema: tagsListOutputSchema, annotations: READ_ONLY, handler: async (context, rawArgs) => { const args = tagsListArgsSchema.parse(rawArgs) as TagsListArgs; return listTags(context, args); }, }, ]; - src/domain/tags.ts:13-21 (helper)The extractAllTags() helper function that parses frontmatter and the note body to separate frontmatterTags, inlineTags, and their union allTags.
export function extractAllTags(content: string) { const parsed = parseFrontmatter(content); const frontmatterTags = getFrontmatterTags(parsed.data); const inlineTags = Array.from(content.matchAll(TAG_PATTERN), (match) => match[1]).filter( (tag): tag is string => typeof tag === "string" && tag.length > 0, ); const allTags = Array.from(new Set([...frontmatterTags, ...inlineTags])); return { frontmatterTags, inlineTags, allTags }; }