From d35a6a0ef366f86aeba28c06f40e44cd29cf1f07 Mon Sep 17 00:00:00 2001 From: haoyuren <13851610112@163.com> Date: Tue, 28 Jul 2026 06:29:04 +0800 Subject: Codex/agent-neutral setup, terminal IME fix, hide own overlay cursor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Write AGENTS.md (the cross-tool agent-instructions standard) at the project root alongside .claude/CLAUDE.md, generated from one guide; includes an Agent Setup section with the project-specific Codex MCP registration command. AGENTS.md is excluded from Overleaf sync. - MCP server resolves the project directory from its own script location when cwd doesn't contain the state file, so clients that launch MCP servers from a global config (Codex) work without special setup - Terminal: swallow the duplicate compositionend commit when switching input sources mid-composition (xterm finalizes on the keydown and then again on compositionend, sending pinyin text twice) - Don't render our own colored overlay cursor — the native caret already marks our position; overlay cursors are collaborators-only (web parity) Co-Authored-By: Claude Fable 5 --- src/mcp/lattex.mjs | 39 ++++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-) (limited to 'src/mcp/lattex.mjs') diff --git a/src/mcp/lattex.mjs b/src/mcp/lattex.mjs index 64520f7..e0cb6cd 100644 --- a/src/mcp/lattex.mjs +++ b/src/mcp/lattex.mjs @@ -3,8 +3,9 @@ // Licensed under AGPL-3.0 - see LICENSE file // MCP Server: LatteX -// Provides tools for Claude Code to interact with the Overleaf project: -// comments, chat, file listing, compilation + debugging +// Provides tools for coding agents (Claude Code, Codex, any MCP client) to +// interact with the Overleaf project: comments, chat, file listing, +// compilation + debugging import { Server } from '@modelcontextprotocol/sdk/server/index.js' import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js' @@ -13,14 +14,34 @@ import { ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js' import { readFileSync, readdirSync, statSync, writeFileSync, existsSync, unlinkSync } from 'fs' -import { join, relative } from 'path' +import { join, relative, dirname } from 'path' +import { fileURLToPath } from 'url' import https from 'https' +// ── Project directory resolution ────────────────────────────── +// +// Claude Code launches MCP servers with the project as cwd, but other MCP +// clients (Codex reads global config) may not. The packaged server is copied +// into /.lattex/lattex-mcp.mjs, so the script's own location also +// identifies the project. Resolution order: cwd, then script parent dir. + +function resolveProjectDir() { + const cwd = process.cwd() + if (existsSync(join(cwd, '.lattex-mcp.json'))) return cwd + try { + const scriptDir = dirname(fileURLToPath(import.meta.url)) + const candidate = dirname(scriptDir) // /.lattex/.. = + if (existsSync(join(candidate, '.lattex-mcp.json'))) return candidate + } catch { /* fall through */ } + return cwd +} + +const PROJECT_DIR = resolveProjectDir() + // ── State ────────────────────────────────────────────────────── function readState() { - const cwd = process.cwd() - const statePath = join(cwd, '.lattex-mcp.json') + const statePath = join(PROJECT_DIR, '.lattex-mcp.json') try { return JSON.parse(readFileSync(statePath, 'utf-8')) } catch { @@ -847,7 +868,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => { // ── Project ─────────────────────────────────── case 'list_project_files': { - const cwd = process.cwd() + const cwd = PROJECT_DIR const files = walkDir(cwd, cwd) .filter(f => !f.path.startsWith('.')) @@ -870,7 +891,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => { case 'compile_latex': { const mainFile = args?.main_file || null - const cwd = process.cwd() + const cwd = PROJECT_DIR const requestPath = join(cwd, '.lattex-compile-request') const resultPath = join(cwd, '.lattex-compile-result') @@ -1015,7 +1036,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => { } case 'get_online_users': { - const cwd = process.cwd() + const cwd = PROJECT_DIR const usersPath = join(cwd, '.lattex-online-users.json') try { const users = JSON.parse(readFileSync(usersPath, 'utf-8')) @@ -1032,7 +1053,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => { // ── PDF ────────────────────────────────────────── case 'read_compiled_pdf': { - const cwd = process.cwd() + const cwd = PROJECT_DIR const pdfPath = join(cwd, '.build', 'output.pdf') try { statSync(pdfPath) -- cgit v1.2.3