Skip to main content
Glama
index.ts3.3 kB
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import type { CallToolResult, ToolAnnotations, } from "@modelcontextprotocol/sdk/types.js"; import state from "@/config.js"; import { getGlobalVaultManager } from "@/utils/getVaultManager.js"; import { type OrganizeAttachmentsParams, organizeAttachmentsParamsSchema, } from "./params.js"; import { genreateOrganizationTasks } from "./utils.js"; export const name = "organize_attachments"; export const annotations: ToolAnnotations = { title: "Organize Attachments", openWorldHint: true, }; export const description = ` Scans a specified markdown file for linked images (or other attachments), moves them to a dedicated folder named after the document's title, and updates the links within the markdown file automatically. Use Cases: - When a post is finalized and you want to clean up all associated images into a neat folder. - To automatically organize attachments for better vault management. Example Workflow: 1. Specify 'my-awesome-post.md' as the fileName. 2. The tool finds the 'title' property in the frontmatter (e.g., "My Awesome Post"). 3. It finds all image links like ![[my-image.png]]. 4. It creates a folder at '{vault}/images/My Awesome Post/'. 5. It moves 'my-image.png' into that new folder. 6. It updates the link in the markdown file to ![[images/My Awesome Post/my-image.png]]. `; export const register = (mcpServer: McpServer) => { mcpServer.registerTool( name, { title: annotations.title || name, description: description, inputSchema: organizeAttachmentsParamsSchema.shape, annotations: annotations, }, execute, ); }; export const execute = async ( params: OrganizeAttachmentsParams, ): Promise<CallToolResult> => { const vaultDirPath = state.vaultPath; if (!vaultDirPath) { return { isError: true, content: [ { type: "text", text: JSON.stringify({ error: "VAULT_DIR_PATH is not set" }), }, ], }; } let vaultManager = null; try { vaultManager = getGlobalVaultManager(); } catch (e) { return { isError: true, content: [ { type: "text", text: JSON.stringify({ error: (e as Error).message }) }, ], }; } try { await vaultManager.initialize(); const documents = await vaultManager.searchDocuments(params.keyword); if (documents.length === 0) { return { isError: true, content: [ { type: "text", text: JSON.stringify({ error: `No document found for keyword: ${params.keyword}`, }), }, ], }; } const organizationTasks = genreateOrganizationTasks( documents, vaultDirPath, ); const results = await Promise.all(organizationTasks.map((task) => task())); return { isError: false, content: [ { type: "text", text: JSON.stringify( { summary: `Processed ${documents.length} document(s).`, details: results, }, null, 2, ), }, ], }; } catch (error) { return { isError: true, content: [ { type: "text", text: JSON.stringify({ error: (error as Error).message }, null, 2), }, ], }; } }; export default { name, description, annotations, inputSchema: organizeAttachmentsParamsSchema.shape, execute, register, };

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/sunub/obsidian-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server