Skip to main content
Glama
Mustawphar-Tusk

MCP-Local-SharePoint-Server-Setup

Corporate SharePoint MCP — Finance Pilot M005L

This milestone keeps the MCP service local and read-only while using a OneDrive shortcut to expose an approved SharePoint folder under the signed-in Windows user's existing SharePoint access.

Added in M005L

  • sharepoint_list_folder (filters local OneDrive clutter such as desktop.ini)

  • sharepoint_inspect_excel

  • sharepoint_read_excel_range

  • .xlsx only for this milestone

  • 100 MiB (configurable with EXCEL_MAX_FILE_SIZE_MB) workbook cap

  • range requests capped at 100 rows × 30 columns

  • Excel opened using openpyxl read-only mode with cached formula values (data_only=True)

  • all file paths must resolve beneath SHAREPOINT_SYNC_ROOT

  • no create/update/delete/move/rename tools

Related MCP server: ExcelReadMCP

Install/update dependencies

pip install -r .\requirements.txt

Run tests

$env:PYTHONPATH = "$PWD\src"
pytest -q

Run server

python -m sharepoint_mcp.server

Test the real synced workbook

In a second PowerShell window:

.\.venv\Scripts\Activate.ps1
$env:PYTHONPATH = "$PWD\src"
python .\scripts\test_excel_reader.py

The script expects SalesDelivery Note.xlsx in the configured root. It inspects the workbook, reads A1:J10 from the first worksheet, and confirms ../ remains blocked.

M006L - Safe document discovery

This milestone adds sharepoint_search_files, a recursive metadata-only search inside SHAREPOINT_SYNC_ROOT.

It searches:

  • file names

  • approved-root-relative paths

It deliberately does not open file contents during discovery. This avoids hydrating or parsing large OneDrive-backed workbooks simply to locate them.

Example:

sharepoint_search_files(
    query="sales delivery",
    extension="xlsx",
    max_results=10
)

The tool:

  • remains read-only

  • blocks ../ traversal

  • ignores desktop.ini, Thumbs.db, and temporary ~$ Office files

  • caps a request at 50 returned results

  • caps one scan at 10,000 files

  • returns relative paths rather than exposing the full local Windows path

Run:

pytest -q tests
python .\scripts\test_document_search.py

M007L - Content-aware Excel querying

Adds two read-only tools:

  • sharepoint_get_excel_columns

  • sharepoint_find_excel_rows

The first discovers every named header in a worksheet. The second scans a bounded number of rows and returns matching records using one named business column.

Safety limits:

  • SharePoint sync root sandbox still enforced

  • .xlsx only

  • workbook opened read-only

  • at most 500,000 rows scanned per request

  • at most 100 matching rows returned

  • at most 20 returned columns

  • no edit, rename, move, delete, or upload capability

Example:

sharepoint_find_excel_rows(
    relative_path="SalesDelivery Note.xlsx",
    sheet_name="Data",
    column_name="Packing Slip",
    search_value="GRP0000124",
    match_mode="equals",
    return_columns_csv="Product Id,Packing Slip,Quantity"
)

Live test:

pytest -q tests
python .\scripts\test_excel_content_query.py

M007.1 - Query completeness and continuation

This patch prevents a partial worksheet scan from being mistaken for a complete answer.

sharepoint_find_excel_rows now returns:

  • scan_complete

  • next_start_row

  • worksheet_max_row

The default scan allowance is now 500,000 rows, enough to cover the current 443,759-row Finance workbook in one call. If a future worksheet exceeds the bounded scan or the result cap is reached, Claude can continue with start_row=next_start_row.

The reader also narrows the streamed Excel column window to only the filter column and requested output columns, reducing unnecessary work on wide sheets.

Run:

pytest -q tests
python .\scripts\test_excel_content_query.py

M008L - Multi-condition Finance queries and aggregations

Adds:

  • sharepoint_query_excel

  • sharepoint_aggregate_excel

Multi-condition filters are passed as a bounded JSON array, for example:

[
  {"column":"Business Unit","operator":"equals","value":"Dean"},
  {"column":"Delivery Date","operator":"gte","value":"2026-01-01"},
  {"column":"Delivery Date","operator":"lte","value":"2026-12-31"}
]

Supported filter operators:

  • equals / not_equals

  • contains / starts_with / ends_with

  • gt / gte / lt / lte

  • is_blank / is_not_blank

Aggregations:

  • count

  • sum

  • avg

  • min

  • max

  • optional group_by_column

Guardrails:

  • maximum 8 filter conditions

  • maximum 500,000 scanned rows

  • maximum 100 returned query rows

  • maximum 20 returned columns

  • maximum 100 aggregation groups

  • aggregations refuse partial scans

  • strict SharePoint sync-root sandbox

  • .xlsx only

  • read-only; no write/delete/move/upload tools

Run:

pytest -q tests
python .\scripts\test_finance_multiquery.py

M009L - Claude Desktop local connection

Adds a dedicated local stdio transport entry point:

python -m sharepoint_mcp.desktop

The HTTP development server remains available separately:

python -m sharepoint_mcp.server

Claude Desktop should launch the stdio process itself, so port 8000 is not required for the Desktop connection.

Generate a machine-specific config snippet:

$env:PYTHONPATH = "$PWD\\src"
python .\\scripts\\show_claude_desktop_config.py

The generated JSON contains local executable/folder paths and read-only pilot settings only. It does not include Entra secrets.

Related MCP Connectors

Related MCP Servers