Skip to main content
Glama

Sharepoint MCP Server

by BrianCusack
index.ts7.72 kB
import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { z } from "zod"; import { register } from "microsoft-graph/services/context"; import { getEnvironmentVariable } from "microsoft-graph/services/environmentVariable"; import { TenantId } from "microsoft-graph/models/TenantId"; import { ClientId } from "microsoft-graph/models/ClientId"; import { SiteId } from "microsoft-graph/models/SiteId"; import { ClientSecret } from "microsoft-graph/models/ClientSecret"; import dotenv from "dotenv"; import { createDriveRef } from "microsoft-graph/services/drive"; import { createSiteRef } from "microsoft-graph/services/site"; import { DriveId } from "microsoft-graph/models/DriveId"; import listDriveItems from "microsoft-graph/operations/driveItem/listDriveItems"; import { createDriveItemRef } from "microsoft-graph/services/driveItem"; import { DriveItemId } from "microsoft-graph/models/DriveItemId"; import getDriveItem from "microsoft-graph/operations/driveItem/getDriveItem"; import listSites from "microsoft-graph/operations/site/listSites"; dotenv.config(); // Initialize the MCP server and SharePoint connector async function createSharepointMcpServer() { const tenantId = getEnvironmentVariable("TENANT_ID") as TenantId; const clientId = getEnvironmentVariable("CLIENT_ID") as ClientId; const clientSecret = getEnvironmentVariable("CLIENT_SECRET") as ClientSecret; const driveId = getEnvironmentVariable("DRIVE_ID") as DriveId; const siteId = getEnvironmentVariable("SITE_ID") as SiteId; // Create the server const server = new McpServer({ name: "SharePoint Server", version: "1.0.0" }); const contextRef = register(tenantId, clientId, clientSecret); const siteRef = createSiteRef(contextRef, siteId); const driveRef = createDriveRef(siteRef, driveId); // Resource: Folder contents (root or specific folder) server.resource( "folder", new ResourceTemplate("sharepoint://folder/{folderId?}", { list: undefined }), async (uri) => { const items = await listDriveItems(driveRef); return { contents: [{ uri: uri.href, text: JSON.stringify(items, null, 2) }] }; } ); // Resource: Sites server.resource( "sites", "sharepoint://sites", async (uri) => { const items = await listSites(contextRef); return { contents: [{ uri: uri.href, text: JSON.stringify(items, null, 2) }] }; } ); // Resource: Document content server.resource( "document", new ResourceTemplate("sharepoint://document/{documentId}", { list: undefined }), async (uri, { documentId }) => { const driveItemRef = createDriveItemRef(driveRef, documentId as DriveItemId); const result = await getDriveItem(driveItemRef); return { contents: [{ uri: uri.href, text: result.content ? (typeof result.content === 'string' ? result.content : JSON.stringify(result.content, null, 2)) : "No content available" // Fallback value }] }; } ); // Tool: Search for documents server.tool( "search-documents", { query: z.string().describe("Search query to find documents"), maxResults: z.string().optional().describe("Maximum number of results to return (as a string)") }, async ({ query, maxResults = 10 }) => { try { const driveRef = createDriveRef(siteRef, driveId); const driveItems = await listDriveItems(driveRef); const results = driveItems.filter((item: any) => item.name.includes(query)).slice(0, parseInt(maxResults.toString(), 10)); return { content: [{ type: "text", text: JSON.stringify(results, null, 2) // Ensure this is a valid string }] }; } catch (error) { return { content: [{ type: "text", text: `Error searching documents: ${error}` }], isError: true }; } } ); // Download document content server.tool( "download-document", { documentId: z.string().describe("The ID of the document to download") }, async ({ documentId }) => { try { const driveItemRef = createDriveItemRef(driveRef, documentId as DriveItemId); const result = await getDriveItem(driveItemRef); return { content: [{ type: "text", text: result.content ? (typeof result.content === 'string' ? result.content : JSON.stringify(result.content, null, 2)) : "No content available" // Fallback value }] }; } catch (error) { return { content: [{ type: "text", text: `Error downloading document: ${error}` }], isError: true }; } } ); // Prompt: Search and summarize a document server.prompt( "document-summary", { documentId: z.string().describe("The ID of the document to summarize") }, ({ documentId }) => ({ messages: [{ role: "user", content: { type: "text", text: `Please retrieve the document with ID ${documentId} using the sharepoint://document/${documentId} resource, then provide a concise summary of its key points, main topics, and important information.` } }] }) ); // Prompt: Find relevant documents server.prompt( "find-relevant-documents", { topic: z.string().describe("The topic or subject to find documents about"), maxResults: z.string().optional().describe("Maximum number of results to return (as a string)") }, ({ topic, maxResults = "5" }) => ({ messages: [{ role: "user", content: { type: "text", text: `Please use the search-documents tool to find up to ${maxResults} documents related to "${topic}". For each document, provide the title, author, last modified date, and a brief description of what it appears to contain based on the metadata.` } }] }) ); // Prompt: Explore folder contents server.prompt( "explore-folder", { folderId: z.string().optional().describe("The ID of the folder to explore (leave empty for root folder)") }, ({ folderId }) => ({ messages: [{ role: "user", content: { type: "text", text: folderId ? `Please explore the contents of the folder with ID ${folderId} using the sharepoint://folder/${folderId} resource. List all documents and subfolders, organizing them by type and providing key details about each item.` : `Please explore the contents of the root folder using the sharepoint://folder resource. List all documents and subfolders, organizing them by type and providing key details about each item.` } }] }) ); return server; } // Example usage async function main() { // Create and start the server const server = await createSharepointMcpServer(); // Connect using stdio transport const transport = new StdioServerTransport(); await server.connect(transport); } // Run the server main().catch(error => { console.error("Error starting server:", error); process.exit(1); });

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/BrianCusack/mcpsharepoint'

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