fix: add complete input schemas to all link and tag/alias tools
Fixed all remaining tools in links.ts and tags-aliases.ts to properly
expose their input parameters in the tools/list response, matching the
pattern used in file-operations.ts and search.ts.
Links.ts (5 tools):
- obsidian_get_backlinks: Added 5 params (file, path, counts, total, format)
- obsidian_list_outgoing_links: Added 3 params (file, path, total)
- obsidian_list_unresolved_links: Added 4 params (total, counts, verbose, format)
- obsidian_list_deadends: Added 2 params (total, all)
- obsidian_list_orphans: Added 2 params (total, all)
Tags-Aliases.ts (4 tools):
- obsidian_list_tags: Added 7 params (file, path, total, counts, sort, format, active)
- obsidian_search_by_tag: Added 3 params (name required, total, verbose)
* Renamed from obsidian_get_tag_info for consistency
- obsidian_get_tag_count: Added 1 param (name required)
- obsidian_list_aliases: Added 5 params (file, path, total, verbose, active)
All parameters verified against 'obsidian help <command>' output.
Changes to manifest.json:
- Updated tool name: obsidian_get_tag_info → obsidian_search_by_tag
Before: Empty properties: {} on 9 tools
After: Full parameter schemas with types, descriptions, and required fields
Build: ✅ 0 TypeScript errors
Total tools with complete schemas: 28/28 ✅
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -99,7 +99,7 @@
|
|||||||
"description": "List all tags in the vault or in a specific note. Optionally include usage counts and sort by frequency or name."
|
"description": "List all tags in the vault or in a specific note. Optionally include usage counts and sort by frequency or name."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "obsidian_get_tag_info",
|
"name": "obsidian_search_by_tag",
|
||||||
"description": "Get detailed information about a specific tag, including which notes use it and how many times."
|
"description": "Get detailed information about a specific tag, including which notes use it and how many times."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -22,10 +22,28 @@ export async function registerLinkTools(server: ObsidianMCPServer): Promise<void
|
|||||||
server.registerTool(
|
server.registerTool(
|
||||||
'obsidian_get_backlinks',
|
'obsidian_get_backlinks',
|
||||||
'Get all backlinks (incoming links) to a note. Shows which notes reference this note. Optionally include link counts.',
|
'Get all backlinks (incoming links) to a note. Shows which notes reference this note. Optionally include link counts.',
|
||||||
{ type: 'object', properties: {} },
|
{
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
file: { type: 'string', description: 'Target file name' },
|
||||||
|
path: { type: 'string', description: 'Target file path' },
|
||||||
|
counts: { type: 'boolean', description: 'Include link counts' },
|
||||||
|
total: { type: 'boolean', description: 'Return backlink count' },
|
||||||
|
format: { type: 'string', enum: ['json', 'tsv', 'csv'], description: 'Output format (default: tsv)' },
|
||||||
|
},
|
||||||
|
},
|
||||||
createToolHandler(
|
createToolHandler(
|
||||||
'Get backlinks to a note',
|
'Get backlinks to a note',
|
||||||
{ type: 'object', properties: {} },
|
{
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
file: { type: 'string', description: 'Target file name' },
|
||||||
|
path: { type: 'string', description: 'Target file path' },
|
||||||
|
counts: { type: 'boolean', description: 'Include link counts' },
|
||||||
|
total: { type: 'boolean', description: 'Return backlink count' },
|
||||||
|
format: { type: 'string', enum: ['json', 'tsv', 'csv'], description: 'Output format' },
|
||||||
|
},
|
||||||
|
},
|
||||||
async (args) => {
|
async (args) => {
|
||||||
const validated = fileIdentifierSchema.parse(args) as any;
|
const validated = fileIdentifierSchema.parse(args) as any;
|
||||||
const sanitized = sanitizeParameters(validated) as any;
|
const sanitized = sanitizeParameters(validated) as any;
|
||||||
@@ -34,6 +52,7 @@ export async function registerLinkTools(server: ObsidianMCPServer): Promise<void
|
|||||||
if (sanitized.file) cmdArgs.push(formatParam('file', sanitized.file));
|
if (sanitized.file) cmdArgs.push(formatParam('file', sanitized.file));
|
||||||
if (sanitized.path) cmdArgs.push(formatParam('path', sanitized.path));
|
if (sanitized.path) cmdArgs.push(formatParam('path', sanitized.path));
|
||||||
if ((args as any).counts) cmdArgs.push('counts');
|
if ((args as any).counts) cmdArgs.push('counts');
|
||||||
|
if ((args as any).total) cmdArgs.push('total');
|
||||||
if ((args as any).format) cmdArgs.push(formatParam('format', (args as any).format));
|
if ((args as any).format) cmdArgs.push(formatParam('format', (args as any).format));
|
||||||
|
|
||||||
const result = await executeObsidianCommand('backlinks', cmdArgs);
|
const result = await executeObsidianCommand('backlinks', cmdArgs);
|
||||||
@@ -56,12 +75,26 @@ export async function registerLinkTools(server: ObsidianMCPServer): Promise<void
|
|||||||
|
|
||||||
// T051: Get outgoing links tool
|
// T051: Get outgoing links tool
|
||||||
server.registerTool(
|
server.registerTool(
|
||||||
'obsidian_get_outgoing_links',
|
'obsidian_list_outgoing_links',
|
||||||
'Get all outgoing links from a note. Shows which notes this note references. Useful for understanding note connections.',
|
'Get all outgoing links from a note. Shows which notes this note references. Useful for understanding note connections.',
|
||||||
{ type: 'object', properties: {} },
|
{
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
file: { type: 'string', description: 'File name' },
|
||||||
|
path: { type: 'string', description: 'File path' },
|
||||||
|
total: { type: 'boolean', description: 'Return link count' },
|
||||||
|
},
|
||||||
|
},
|
||||||
createToolHandler(
|
createToolHandler(
|
||||||
'Get outgoing links from a note',
|
'Get outgoing links from a note',
|
||||||
{ type: 'object', properties: {} },
|
{
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
file: { type: 'string', description: 'File name' },
|
||||||
|
path: { type: 'string', description: 'File path' },
|
||||||
|
total: { type: 'boolean', description: 'Return link count' },
|
||||||
|
},
|
||||||
|
},
|
||||||
async (args) => {
|
async (args) => {
|
||||||
const validated = fileIdentifierSchema.parse(args) as any;
|
const validated = fileIdentifierSchema.parse(args) as any;
|
||||||
const sanitized = sanitizeParameters(validated) as any;
|
const sanitized = sanitizeParameters(validated) as any;
|
||||||
@@ -69,19 +102,18 @@ export async function registerLinkTools(server: ObsidianMCPServer): Promise<void
|
|||||||
const cmdArgs: string[] = [];
|
const cmdArgs: string[] = [];
|
||||||
if (sanitized.file) cmdArgs.push(formatParam('file', sanitized.file));
|
if (sanitized.file) cmdArgs.push(formatParam('file', sanitized.file));
|
||||||
if (sanitized.path) cmdArgs.push(formatParam('path', sanitized.path));
|
if (sanitized.path) cmdArgs.push(formatParam('path', sanitized.path));
|
||||||
if ((args as any).format) cmdArgs.push(formatParam('format', (args as any).format));
|
if ((args as any).total) cmdArgs.push('total');
|
||||||
|
|
||||||
const result = await executeObsidianCommand('links', cmdArgs);
|
const result = await executeObsidianCommand('links', cmdArgs);
|
||||||
handleCLIResult(result, { operation: 'outgoing_links', identifier: sanitized.file || sanitized.path });
|
handleCLIResult(result, { operation: 'outgoing_links', identifier: sanitized.file || sanitized.path });
|
||||||
|
|
||||||
const format = (args as any).format || 'text';
|
const parsedData = parseOutput(result.stdout, 'text');
|
||||||
const parsedData = parseOutput(result.stdout, format);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
content: [
|
content: [
|
||||||
{
|
{
|
||||||
type: 'text',
|
type: 'text',
|
||||||
text: formatForMCP(parsedData, format),
|
text: formatForMCP(parsedData, 'text'),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
@@ -93,14 +125,33 @@ export async function registerLinkTools(server: ObsidianMCPServer): Promise<void
|
|||||||
server.registerTool(
|
server.registerTool(
|
||||||
'obsidian_list_unresolved_links',
|
'obsidian_list_unresolved_links',
|
||||||
'List all unresolved (broken) wikilinks in the vault. Shows links pointing to notes that don\'t exist. Useful for finding content gaps.',
|
'List all unresolved (broken) wikilinks in the vault. Shows links pointing to notes that don\'t exist. Useful for finding content gaps.',
|
||||||
{ type: 'object', properties: {} },
|
{
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
total: { type: 'boolean', description: 'Return unresolved link count' },
|
||||||
|
counts: { type: 'boolean', description: 'Include link counts' },
|
||||||
|
verbose: { type: 'boolean', description: 'Include source files' },
|
||||||
|
format: { type: 'string', enum: ['json', 'tsv', 'csv'], description: 'Output format (default: tsv)' },
|
||||||
|
},
|
||||||
|
},
|
||||||
createToolHandler(
|
createToolHandler(
|
||||||
'List unresolved/broken links',
|
'List unresolved/broken links',
|
||||||
{ type: 'object', properties: {} },
|
{
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
total: { type: 'boolean', description: 'Return unresolved link count' },
|
||||||
|
counts: { type: 'boolean', description: 'Include link counts' },
|
||||||
|
verbose: { type: 'boolean', description: 'Include source files' },
|
||||||
|
format: { type: 'string', enum: ['json', 'tsv', 'csv'], description: 'Output format' },
|
||||||
|
},
|
||||||
|
},
|
||||||
async (args) => {
|
async (args) => {
|
||||||
const sanitized = sanitizeParameters(args as any) as any;
|
const sanitized = sanitizeParameters(args as any) as any;
|
||||||
|
|
||||||
const cmdArgs: string[] = [];
|
const cmdArgs: string[] = [];
|
||||||
|
if (sanitized.total) cmdArgs.push('total');
|
||||||
|
if (sanitized.counts) cmdArgs.push('counts');
|
||||||
|
if (sanitized.verbose) cmdArgs.push('verbose');
|
||||||
if (sanitized.format) cmdArgs.push(formatParam('format', sanitized.format));
|
if (sanitized.format) cmdArgs.push(formatParam('format', sanitized.format));
|
||||||
|
|
||||||
const result = await executeObsidianCommand('unresolved', cmdArgs);
|
const result = await executeObsidianCommand('unresolved', cmdArgs);
|
||||||
@@ -125,27 +176,39 @@ export async function registerLinkTools(server: ObsidianMCPServer): Promise<void
|
|||||||
server.registerTool(
|
server.registerTool(
|
||||||
'obsidian_list_deadends',
|
'obsidian_list_deadends',
|
||||||
'List all dead-end notes (notes with no outgoing links). These notes don\'t connect to anything else in the vault.',
|
'List all dead-end notes (notes with no outgoing links). These notes don\'t connect to anything else in the vault.',
|
||||||
{ type: 'object', properties: {} },
|
{
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
total: { type: 'boolean', description: 'Return dead-end count' },
|
||||||
|
all: { type: 'boolean', description: 'Include non-markdown files' },
|
||||||
|
},
|
||||||
|
},
|
||||||
createToolHandler(
|
createToolHandler(
|
||||||
'List dead-end notes',
|
'List dead-end notes',
|
||||||
{ type: 'object', properties: {} },
|
{
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
total: { type: 'boolean', description: 'Return dead-end count' },
|
||||||
|
all: { type: 'boolean', description: 'Include non-markdown files' },
|
||||||
|
},
|
||||||
|
},
|
||||||
async (args) => {
|
async (args) => {
|
||||||
const sanitized = sanitizeParameters(args as any) as any;
|
const sanitized = sanitizeParameters(args as any) as any;
|
||||||
|
|
||||||
const cmdArgs: string[] = [];
|
const cmdArgs: string[] = [];
|
||||||
if (sanitized.format) cmdArgs.push(formatParam('format', sanitized.format));
|
if (sanitized.total) cmdArgs.push('total');
|
||||||
|
if (sanitized.all) cmdArgs.push('all');
|
||||||
|
|
||||||
const result = await executeObsidianCommand('deadends', cmdArgs);
|
const result = await executeObsidianCommand('deadends', cmdArgs);
|
||||||
handleCLIResult(result, { operation: 'deadends' });
|
handleCLIResult(result, { operation: 'deadends' });
|
||||||
|
|
||||||
const format = sanitized.format || 'text';
|
const parsedData = parseOutput(result.stdout, 'text');
|
||||||
const parsedData = parseOutput(result.stdout, format);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
content: [
|
content: [
|
||||||
{
|
{
|
||||||
type: 'text',
|
type: 'text',
|
||||||
text: formatForMCP(parsedData, format),
|
text: formatForMCP(parsedData, 'text'),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
@@ -157,27 +220,39 @@ export async function registerLinkTools(server: ObsidianMCPServer): Promise<void
|
|||||||
server.registerTool(
|
server.registerTool(
|
||||||
'obsidian_list_orphans',
|
'obsidian_list_orphans',
|
||||||
'List all orphan notes (notes with no incoming links/backlinks). These notes aren\'t referenced by any other notes.',
|
'List all orphan notes (notes with no incoming links/backlinks). These notes aren\'t referenced by any other notes.',
|
||||||
{ type: 'object', properties: {} },
|
{
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
total: { type: 'boolean', description: 'Return orphan count' },
|
||||||
|
all: { type: 'boolean', description: 'Include non-markdown files' },
|
||||||
|
},
|
||||||
|
},
|
||||||
createToolHandler(
|
createToolHandler(
|
||||||
'List orphan notes',
|
'List orphan notes',
|
||||||
{ type: 'object', properties: {} },
|
{
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
total: { type: 'boolean', description: 'Return orphan count' },
|
||||||
|
all: { type: 'boolean', description: 'Include non-markdown files' },
|
||||||
|
},
|
||||||
|
},
|
||||||
async (args) => {
|
async (args) => {
|
||||||
const sanitized = sanitizeParameters(args as any) as any;
|
const sanitized = sanitizeParameters(args as any) as any;
|
||||||
|
|
||||||
const cmdArgs: string[] = [];
|
const cmdArgs: string[] = [];
|
||||||
if (sanitized.format) cmdArgs.push(formatParam('format', sanitized.format));
|
if (sanitized.total) cmdArgs.push('total');
|
||||||
|
if (sanitized.all) cmdArgs.push('all');
|
||||||
|
|
||||||
const result = await executeObsidianCommand('orphans', cmdArgs);
|
const result = await executeObsidianCommand('orphans', cmdArgs);
|
||||||
handleCLIResult(result, { operation: 'orphans' });
|
handleCLIResult(result, { operation: 'orphans' });
|
||||||
|
|
||||||
const format = sanitized.format || 'text';
|
const parsedData = parseOutput(result.stdout, 'text');
|
||||||
const parsedData = parseOutput(result.stdout, format);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
content: [
|
content: [
|
||||||
{
|
{
|
||||||
type: 'text',
|
type: 'text',
|
||||||
text: formatForMCP(parsedData, format),
|
text: formatForMCP(parsedData, 'text'),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -21,10 +21,32 @@ export async function registerTagsAndAliasesTools(server: ObsidianMCPServer): Pr
|
|||||||
server.registerTool(
|
server.registerTool(
|
||||||
'obsidian_list_tags',
|
'obsidian_list_tags',
|
||||||
'List all tags in the vault or in a specific note. Optionally include usage counts and sort by frequency or name.',
|
'List all tags in the vault or in a specific note. Optionally include usage counts and sort by frequency or name.',
|
||||||
{ type: 'object', properties: {} },
|
{
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
file: { type: 'string', description: 'File name' },
|
||||||
|
path: { type: 'string', description: 'File path' },
|
||||||
|
total: { type: 'boolean', description: 'Return tag count' },
|
||||||
|
counts: { type: 'boolean', description: 'Include tag counts' },
|
||||||
|
sort: { type: 'string', enum: ['count'], description: 'Sort by count (default: name)' },
|
||||||
|
format: { type: 'string', enum: ['json', 'tsv', 'csv'], description: 'Output format (default: tsv)' },
|
||||||
|
active: { type: 'boolean', description: 'Show tags for active file' },
|
||||||
|
},
|
||||||
|
},
|
||||||
createToolHandler(
|
createToolHandler(
|
||||||
'List tags in vault or note',
|
'List tags in vault or note',
|
||||||
{ type: 'object', properties: {} },
|
{
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
file: { type: 'string', description: 'File name' },
|
||||||
|
path: { type: 'string', description: 'File path' },
|
||||||
|
total: { type: 'boolean', description: 'Return tag count' },
|
||||||
|
counts: { type: 'boolean', description: 'Include tag counts' },
|
||||||
|
sort: { type: 'string', enum: ['count'], description: 'Sort by count' },
|
||||||
|
format: { type: 'string', enum: ['json', 'tsv', 'csv'], description: 'Output format' },
|
||||||
|
active: { type: 'boolean', description: 'Show tags for active file' },
|
||||||
|
},
|
||||||
|
},
|
||||||
async (args) => {
|
async (args) => {
|
||||||
const sanitized = sanitizeParameters(args as any) as any;
|
const sanitized = sanitizeParameters(args as any) as any;
|
||||||
|
|
||||||
@@ -37,9 +59,11 @@ export async function registerTagsAndAliasesTools(server: ObsidianMCPServer): Pr
|
|||||||
cmdArgs.push(formatParam('path', sanitized.path));
|
cmdArgs.push(formatParam('path', sanitized.path));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sanitized.total) cmdArgs.push('total');
|
||||||
if (sanitized.counts) cmdArgs.push('counts');
|
if (sanitized.counts) cmdArgs.push('counts');
|
||||||
if (sanitized.sortBy) cmdArgs.push(formatParam('sort', sanitized.sortBy));
|
if (sanitized.sort) cmdArgs.push(formatParam('sort', sanitized.sort));
|
||||||
if (sanitized.format) cmdArgs.push(formatParam('format', sanitized.format));
|
if (sanitized.format) cmdArgs.push(formatParam('format', sanitized.format));
|
||||||
|
if (sanitized.active) cmdArgs.push('active');
|
||||||
|
|
||||||
const result = await executeObsidianCommand('tags', cmdArgs);
|
const result = await executeObsidianCommand('tags', cmdArgs);
|
||||||
handleCLIResult(result, { operation: 'list_tags' });
|
handleCLIResult(result, { operation: 'list_tags' });
|
||||||
@@ -61,33 +85,49 @@ export async function registerTagsAndAliasesTools(server: ObsidianMCPServer): Pr
|
|||||||
|
|
||||||
// T055: Get tag info tool
|
// T055: Get tag info tool
|
||||||
server.registerTool(
|
server.registerTool(
|
||||||
'obsidian_get_tag_info',
|
'obsidian_search_by_tag',
|
||||||
'Get detailed information about a specific tag, including which notes use it and how many times.',
|
'Get detailed information about a specific tag, including which notes use it and how many times.',
|
||||||
{ type: 'object', properties: {} },
|
{
|
||||||
|
type: 'object',
|
||||||
|
required: ['name'],
|
||||||
|
properties: {
|
||||||
|
name: { type: 'string', description: 'Tag name (required)' },
|
||||||
|
total: { type: 'boolean', description: 'Return occurrence count' },
|
||||||
|
verbose: { type: 'boolean', description: 'Include file list and count' },
|
||||||
|
},
|
||||||
|
},
|
||||||
createToolHandler(
|
createToolHandler(
|
||||||
'Get information about a tag',
|
'Get information about a tag',
|
||||||
{ type: 'object', properties: {} },
|
{
|
||||||
|
type: 'object',
|
||||||
|
required: ['name'],
|
||||||
|
properties: {
|
||||||
|
name: { type: 'string', description: 'Tag name (required)' },
|
||||||
|
total: { type: 'boolean', description: 'Return occurrence count' },
|
||||||
|
verbose: { type: 'boolean', description: 'Include file list and count' },
|
||||||
|
},
|
||||||
|
},
|
||||||
async (args) => {
|
async (args) => {
|
||||||
const sanitized = sanitizeParameters(args as any) as any;
|
const sanitized = sanitizeParameters(args as any) as any;
|
||||||
|
|
||||||
if (!sanitized.tag) {
|
if (!sanitized.name) {
|
||||||
throw new Error('Tag parameter is required');
|
throw new Error('Tag name parameter is required');
|
||||||
}
|
}
|
||||||
|
|
||||||
const cmdArgs: string[] = [formatParam('name', sanitized.tag)];
|
const cmdArgs: string[] = [formatParam('name', sanitized.name)];
|
||||||
if (sanitized.format) cmdArgs.push(formatParam('format', sanitized.format));
|
if (sanitized.total) cmdArgs.push('total');
|
||||||
|
if (sanitized.verbose) cmdArgs.push('verbose');
|
||||||
|
|
||||||
const result = await executeObsidianCommand('tag', cmdArgs);
|
const result = await executeObsidianCommand('tag', cmdArgs);
|
||||||
handleCLIResult(result, { operation: 'tag_info', tag: sanitized.tag });
|
handleCLIResult(result, { operation: 'tag_info', tag: sanitized.name });
|
||||||
|
|
||||||
const format = sanitized.format || 'text';
|
const parsedData = parseOutput(result.stdout, 'text');
|
||||||
const parsedData = parseOutput(result.stdout, format);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
content: [
|
content: [
|
||||||
{
|
{
|
||||||
type: 'text',
|
type: 'text',
|
||||||
text: formatForMCP(parsedData, format),
|
text: formatForMCP(parsedData, 'text'),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
@@ -99,10 +139,28 @@ export async function registerTagsAndAliasesTools(server: ObsidianMCPServer): Pr
|
|||||||
server.registerTool(
|
server.registerTool(
|
||||||
'obsidian_list_aliases',
|
'obsidian_list_aliases',
|
||||||
'List all aliases in the vault or for a specific note. Aliases are alternative names for notes.',
|
'List all aliases in the vault or for a specific note. Aliases are alternative names for notes.',
|
||||||
{ type: 'object', properties: {} },
|
{
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
file: { type: 'string', description: 'File name' },
|
||||||
|
path: { type: 'string', description: 'File path' },
|
||||||
|
total: { type: 'boolean', description: 'Return alias count' },
|
||||||
|
verbose: { type: 'boolean', description: 'Include file paths' },
|
||||||
|
active: { type: 'boolean', description: 'Show aliases for active file' },
|
||||||
|
},
|
||||||
|
},
|
||||||
createToolHandler(
|
createToolHandler(
|
||||||
'List aliases in vault or note',
|
'List aliases in vault or note',
|
||||||
{ type: 'object', properties: {} },
|
{
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
file: { type: 'string', description: 'File name' },
|
||||||
|
path: { type: 'string', description: 'File path' },
|
||||||
|
total: { type: 'boolean', description: 'Return alias count' },
|
||||||
|
verbose: { type: 'boolean', description: 'Include file paths' },
|
||||||
|
active: { type: 'boolean', description: 'Show aliases for active file' },
|
||||||
|
},
|
||||||
|
},
|
||||||
async (args) => {
|
async (args) => {
|
||||||
const sanitized = sanitizeParameters(args as any) as any;
|
const sanitized = sanitizeParameters(args as any) as any;
|
||||||
|
|
||||||
@@ -115,7 +173,9 @@ export async function registerTagsAndAliasesTools(server: ObsidianMCPServer): Pr
|
|||||||
cmdArgs.push(formatParam('path', sanitized.path));
|
cmdArgs.push(formatParam('path', sanitized.path));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sanitized.format) cmdArgs.push(formatParam('format', sanitized.format));
|
if (sanitized.total) cmdArgs.push('total');
|
||||||
|
if (sanitized.verbose) cmdArgs.push('verbose');
|
||||||
|
if (sanitized.active) cmdArgs.push('active');
|
||||||
|
|
||||||
const result = await executeObsidianCommand('aliases', cmdArgs);
|
const result = await executeObsidianCommand('aliases', cmdArgs);
|
||||||
handleCLIResult(result, { operation: 'list_aliases' });
|
handleCLIResult(result, { operation: 'list_aliases' });
|
||||||
@@ -135,5 +195,49 @@ export async function registerTagsAndAliasesTools(server: ObsidianMCPServer): Pr
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
logger.info('Tags and aliases tools registered', { count: 3 });
|
// Additional tool: Get tag count (wrapper for tag with total flag)
|
||||||
|
server.registerTool(
|
||||||
|
'obsidian_get_tag_count',
|
||||||
|
'Count how many notes use a specific tag.',
|
||||||
|
{
|
||||||
|
type: 'object',
|
||||||
|
required: ['name'],
|
||||||
|
properties: {
|
||||||
|
name: { type: 'string', description: 'Tag name (required)' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
createToolHandler(
|
||||||
|
'Get tag usage count',
|
||||||
|
{
|
||||||
|
type: 'object',
|
||||||
|
required: ['name'],
|
||||||
|
properties: {
|
||||||
|
name: { type: 'string', description: 'Tag name (required)' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
async (args) => {
|
||||||
|
const sanitized = sanitizeParameters(args as any) as any;
|
||||||
|
|
||||||
|
if (!sanitized.name) {
|
||||||
|
throw new Error('Tag name parameter is required');
|
||||||
|
}
|
||||||
|
|
||||||
|
const cmdArgs: string[] = [formatParam('name', sanitized.name), 'total'];
|
||||||
|
|
||||||
|
const result = await executeObsidianCommand('tag', cmdArgs);
|
||||||
|
handleCLIResult(result, { operation: 'tag_count', tag: sanitized.name });
|
||||||
|
|
||||||
|
return {
|
||||||
|
content: [
|
||||||
|
{
|
||||||
|
type: 'text',
|
||||||
|
text: result.stdout.trim(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
logger.info('Tags and aliases tools registered', { count: 4 });
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user