MCP Server Integration
The Model Context Protocol (MCP) implementation in glean-powershell provides a PowerShell-native bridge between AI clients and the Glean platform, allowing models to query knowledge bases, chat, and read documents. The server operates as a JSON-RPC 2.0 service over standard I/O, exposing a curated set of tools that replicate the functionality of the official Glean MCP server while supporting both token-based and cookie-based authentication modes.
Architecture and Entrypoint
Section titled “Architecture and Entrypoint”The MCP server is initiated via the Start-GleanMcpServer function, which serves as the primary entrypoint for the module. This function is designed to be invoked directly by AI coding assistants, such as Claude Code, using a command like claude mcp add glean -- pwsh -NoProfile -File /path/to/mcp/Start-GleanMcpServer.ps1 1. The script mcp/Start-GleanMcpServer.ps1 acts as the launcher, importing the core GleanMcp.psm1 module and calling the server start function.
The server communicates exclusively over standard I/O using newline-delimited JSON-RPC messages. To ensure protocol integrity, all logging and verbose output are directed to stderr, while only valid JSON-RPC responses are written to stdout . The server loop reads lines from stdin, parses them as JSON, and dispatches them to the request handler .
Authentication and Connection
Section titled “Authentication and Connection”The server supports two authentication modes determined by the GLEAN_AUTH_MODE environment variable or explicit parameters: token-based and cookie-based.
In token mode (the default), the server uses GLEAN_INSTANCE or GLEAN_BASE_URL along with GLEAN_API_TOKEN to establish a connection via Connect-Glean . This mode relies on the standard PowerShell module cmdlets for API interaction .
In cookie mode, the server attempts to reuse an existing Single Sign-On (SSO) session stored by a prior interactive Connect-Glean -CookieAuth command . It validates the session using Test-GleanConnection before proceeding; if the session is missing or expired, the server exits with a clear error message instructing the user to re-sync their authentication . This mode routes requests through Invoke-GleanWebRequest to interact with the web-client API endpoints .
Exposed Tools
Section titled “Exposed Tools”The server exposes a fixed set of tools via the tools/list JSON-RPC method, defined in Get-GleanMcpTools . These tools are implemented in Invoke-GleanMcpTool, which routes calls to either the typed REST cmdlets (token mode) or the web-client API (cookie mode) .
The core tools include:
glean_search: Searches the company knowledge base and returns ranked results including title, URL, and snippet .glean_chat: Sends a message to Glean Assistant and returns the grounded answer .glean_read_document: Fetches the content or metadata of a specific document by ID or URL .glean_people_search: Searches the company directory for people or teams .
Additionally, an advanced tool named glean_invoke is available if the environment variable GLEAN_MCP_ALLOW_INVOKE is set to 1 . This tool allows the AI client to invoke any cmdlet from the Glean module by name, passing a JSON body as parameters . This provides access to the full 112-operation surface of the module but is disabled by default to prevent unintended side effects 2 .
Request Handling and Response Formatting
Section titled “Request Handling and Response Formatting”The core logic for processing JSON-RPC requests is encapsulated in New-GleanMcpResponse, which is a pure function designed for unit testing . It handles standard MCP methods such as initialize, ping, tools/list, and tools/call .
When a tool is called via tools/call, the server executes the corresponding logic in Invoke-GleanMcpTool and formats the output using specific helper functions:
Format-GleanSearchText: Converts search results into a readable text format with title, URL, and snippet .Format-GleanChatText: Extracts the text fragments from the chat response .ConvertTo-Json: Used for document and people search results to return structured JSON data .
Errors are caught and returned as JSON-RPC responses with isError set to true and a descriptive message in the content text .
#!/usr/bin/env pwsh
# Entry point for the Glean PowerShell MCP server. Register this with Claude Code:
#
# claude mcp add glean -- pwsh -NoProfile -File /path/to/mcp/Start-GleanMcpServer.ps1
#
# with env GLEAN_INSTANCE (or GLEAN_BASE_URL) and GLEAN_API_TOKEN set. Set
# GLEAN_MCP_ALLOW_INVOKE=1 to expose the generic glean_invoke tool (full 112-op surface).
[CmdletBinding()]
param()
$ErrorActionPreference = 'Stop'
# stdout must carry only JSON-RPC; import with non-output streams redirected to stderr.
Import-Module (Join-Path $PSScriptRoot '..' 'Glean' 'Glean.psd1') -Force 3>$null 4>$null 5>$null 6>$null
Import-Module (Join-Path $PSScriptRoot 'GleanMcp.psm1') -Force 3>$null 4>$null 5>$null 6>$null
Start-GleanMcpServer
# A Glean MCP server implemented entirely in PowerShell, layered on the Glean module.
# Speaks JSON-RPC 2.0 over stdio (newline-delimited) and exposes Glean Search / Chat /
# Read-Document / People / Recommendations as MCP tools, replicating the shape of the
# official @gleanwork MCP server. An optional generic 'glean_invoke' tool (off by default)
# exposes the full 112-operation surface.
#
# The protocol handling (New-GleanMcpResponse) is separated from the stdio pump
# (Start-GleanMcpServer) so it can be unit-tested without process plumbing.
$script:GleanMcpServerInfo = @{ name = 'glean-powershell'; version = '1.0.0' }
$script:GleanMcpProtocol = '2024-11-05'
function Get-GleanMcpTools {
[CmdletBinding()]
param([bool] $AllowInvoke)
$tools = [System.Collections.Generic.List[object]]::new()
$tools.Add(@{
name = 'glean_search'
description = 'Search the company knowledge base via Glean and return ranked results (title, URL, snippet).'
inputSchema = @{
type = 'object'
properties = @{
query = @{ type = 'string'; description = 'The search query.' }
pageSize = @{ type = 'integer'; description = 'Maximum results to return (default 10).' }
}
required = @('query')
}
})
$tools.Add(@{
name = 'glean_chat'
description = 'Ask Glean Assistant a question grounded in company knowledge and return its answer.'
inputSchema = @{
type = 'object'
properties = @{ message = @{ type = 'string'; description = 'The question or instruction for Glean Assistant.' } }
required = @('message')
}
})