Skip to main content
Glama

Chat Context MCP

by aolshaun
claude-workspace-extractor.ts3.73 kB
/** * Claude Code Workspace Extractor * * Extracts workspace paths and nicknames from Claude Code JSONL messages */ import type { ClaudeCodeMessage } from './claude-code-db.js'; /** * Extract project path from Claude Code messages * Claude Code stores the project path in the `cwd` field of each message */ export function extractWorkspaceFromClaudeMessages(messages: ClaudeCodeMessage[]): string | null { if (messages.length === 0) { return null; } // Get cwd from first message (all messages in a session have the same cwd) const firstMessage = messages[0]; if (firstMessage && firstMessage.cwd) { return firstMessage.cwd; } return null; } /** * Extract nickname from nickname_current_session tool calls in Claude Code messages */ export function extractNicknameFromClaudeMessages(messages: ClaudeCodeMessage[]): string | null { for (const message of messages) { // Check if this is an assistant message with tool_use if (message.type !== 'assistant' || !message.message.content) { continue; } // Claude Code stores content as an array if (!Array.isArray(message.message.content)) { continue; } for (const content of message.message.content) { // Look for tool_use blocks if (content.type !== 'tool_use') { continue; } // Check if this is a nickname_current_session tool const toolName = content.name || ''; if (toolName === 'mcp__cursor-context__nickname_current_session' || toolName === 'nickname_current_session') { // Extract nickname from input if (content.input && typeof content.input === 'object') { const nickname = (content.input as any).nickname; if (nickname && typeof nickname === 'string') { return nickname; } } } } } return null; } /** * Get project name from workspace path */ export function getProjectNameFromPath(workspacePath: string): string { if (!workspacePath) { return 'unknown'; } // Remove trailing slashes const cleaned = workspacePath.replace(/[\/\\]+$/, ''); if (!cleaned) { return 'unknown'; } // Handle Windows paths const separator = cleaned.includes('\\') ? '\\' : '/'; // Split and get last part const parts = cleaned.split(separator); const lastPart = parts[parts.length - 1]; // Return last part or 'unknown' if empty return lastPart || 'unknown'; } /** * Extract all unique project paths from messages */ export function extractAllWorkspacePathsFromClaudeMessages(messages: ClaudeCodeMessage[]): string[] { const paths = new Set<string>(); for (const message of messages) { if (message.cwd) { paths.add(message.cwd); } } return Array.from(paths); } /** * Check if Claude Code session has a project */ export function hasProjectInClaudeMessages(messages: ClaudeCodeMessage[]): boolean { return extractWorkspaceFromClaudeMessages(messages) !== null; } /** * Get workspace info for Claude Code session */ export interface ClaudeWorkspaceInfo { primaryPath: string | null; projectName: string | null; allPaths: string[]; hasProject: boolean; isMultiWorkspace: boolean; nickname: string | null; } export function getClaudeWorkspaceInfo(messages: ClaudeCodeMessage[]): ClaudeWorkspaceInfo { const allPaths = extractAllWorkspacePathsFromClaudeMessages(messages); const primaryPath = allPaths[0] || null; const nickname = extractNicknameFromClaudeMessages(messages); return { primaryPath, projectName: primaryPath ? getProjectNameFromPath(primaryPath) : null, allPaths, hasProject: allPaths.length > 0, isMultiWorkspace: allPaths.length > 1, nickname }; }

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/aolshaun/chat-context-mcp'

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