commit 321c96b2de3d72a7145a9d0310c8d70b2ca2f029 Author: Jeremy Anderson Date: Fri Jul 3 09:44:15 2026 -0400 second draft of MCP-Drift-State-Tracker diff --git a/README.md b/README.md new file mode 100644 index 0000000..59c10be --- /dev/null +++ b/README.md @@ -0,0 +1,4 @@ +Key design decision: All 20+ language profiles (regex patterns, stub detectors, extension routing) are now pure JSON data. The single index.ts file is a thin runtime that loads and compiles those patterns at startup. To add a new language, you just append an entry to language_profiles.json -- no recompilation, no new parser class. + +To use: cd mcp-drift-state-tracker && npm install && npx tsx src/index.ts + diff --git a/controller_config.json b/controller_config.json new file mode 100644 index 0000000..92a01f2 --- /dev/null +++ b/controller_config.json @@ -0,0 +1,29 @@ +{ + "base_dir": "/mnt/AIs-and-VMs", + "services": { + "Ollama": { + "port": "11434", + "model": "ollama/llama3" + }, + "Open WebUI": { + "port": "8080", + "model": "ollama/llama3" + }, + "Aider Web": { + "port": "8501", + "model": "ollama/llama3" + }, + "Hermes": { + "port": "8000", + "model": "ollama/llama3" + }, + "Odysseus": { + "port": "7000", + "model": "ollama/llama3" + }, + "Dify Engine": { + "port": "5001", + "model": "ollama/llama3" + } + } +} \ No newline at end of file diff --git a/language_profiles.json b/language_profiles.json new file mode 100644 index 0000000..b7e9cbe --- /dev/null +++ b/language_profiles.json @@ -0,0 +1,150 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "MCP Drift State Tracker — Language Profiles", + "description": "Data-driven lexical profiles for multi-language code parsing. All regex patterns, stub detectors, and file-extension routing live here. No code changes needed to add new language support — just extend this JSON.", + + "globalIgnoreDirs": [ + ".git", ".venv", "venv", "__pycache__", "node_modules", "target", + "dist", "build", "out", ".cargo", ".rustup", "obj", "bin", ".idea" + ], + + "stateFileName": ".mcp_drift_state.json", + + "cStyleDefault": { + "imp": "^\\s*(?:import|require|#include)\\s+.*", + "fn": "(?:public|private|protected|static|async|fun|func|function)?\\s*([a-zA-Z_0-9]+)\\s*\\([^)]*\\)\\s*(?:\\{|->|:)?", + "cls": "^\\s*(?:export\\s+)?(?:class|interface|struct|enum)\\s+([a-zA-Z_0-9]+)", + "dec": "^\\s*@([a-zA-Z_0-9]+)" + }, + + "braceProfiles": { + ".rs": { + "imp": "^\\s*(?:pub\\s+)?use\\s+([^;]+);", + "fn": "(?:pub\\s+)?(?:async\\s+)?fn\\s+([a-zA-Z_0-9]+)", + "cls": "^\\s*(?:pub\\s+)?(?:struct|enum|trait)\\s+([a-zA-Z_0-9]+)", + "dec": "^\\s*#\\[([^\\]]+)\\]" + }, + ".go": { + "imp": "^\\s*import\\s+(?:\\([^\\)]+\\)|\"[^\"]+\")", + "fn": "^func\\s+(?:\\([^)]+\\)\\s+)?([a-zA-Z_0-9]+)", + "cls": "^\\s*type\\s+([a-zA-Z_0-9]+)\\s+struct", + "dec": "^\\s*//\\s*@([a-zA-Z_0-9]+)" + }, + ".php": { + "imp": "^\\s*(?:use|require|include)(?:\\s+once)?\\s+([^;]+);", + "fn": "(?:public|private|protected|static)?\\s*function\\s+([a-zA-Z_0-9]+)", + "cls": "^\\s*(?:abstract\\s+)?class\\s+([a-zA-Z_0-9]+)", + "dec": "^\\s*<<([^>>]+)>>" + }, + ".hack": { + "imp": "^\\s*(?:use|require|include)(?:\\s+once)?\\s+([^;]+);", + "fn": "(?:public|private|protected|static)?\\s*function\\s+([a-zA-Z_0-9]+)", + "cls": "^\\s*(?:abstract\\s+)?class\\s+([a-zA-Z_0-9]+)", + "dec": "^\\s*<<([^>>]+)>>" + }, + ".sh": { + "imp": "^\\s*(?:\\.|source)\\s+.*", + "fn": "(?:function\\s+)?([a-zA-Z_0-9\\-]+)\\s*\\(\\s*\\)\\s*\\{?|^\\s*function\\s+([a-zA-Z_0-9\\-]+)", + "cls": "^\\s*class\\s+([a-zA-Z_0-9]+)", + "dec": "^\\s*#\\s*@([a-zA-Z_0-9]+)" + }, + ".zsh": { + "imp": "^\\s*(?:\\.|source)\\s+.*", + "fn": "(?:function\\s+)?([a-zA-Z_0-9\\-]+)\\s*\\(\\s*\\)\\s*\\{?|^\\s*function\\s+([a-zA-Z_0-9\\-]+)", + "cls": "^\\s*class\\s+([a-zA-Z_0-9]+)", + "dec": "^\\s*#\\s*@([a-zA-Z_0-9]+)" + }, + ".ps1": { + "imp": "^\\s*(?:\\.|source)\\s+.*", + "fn": "(?:function\\s+)?([a-zA-Z_0-9\\-]+)\\s*\\(\\s*\\)\\s*\\{?|^\\s*function\\s+([a-zA-Z_0-9\\-]+)", + "cls": "^\\s*class\\s+([a-zA-Z_0-9]+)", + "dec": "^\\s*#\\s*@([a-zA-Z_0-9]+)" + } + }, + + "braceExtensions": [ + ".js", ".jsx", ".ts", ".tsx", ".c", ".cpp", ".h", ".hpp", + ".java", ".cs", ".ec", ".eh", ".pike", ".pmod", ".kt", ".kts", + ".swift", ".dart", ".r" + ], + + "blockEndProfiles": { + ".jl": { + "start": "^\\s*(?:function|macro|mutable\\s+struct)\\s+([a-zA-Z_0-9!]+)", + "end": "^\\s*end\\b", + "inc": "\\b(if|for|while|let|do|try|quote)\\b" + }, + ".lua": { + "start": "^\\s*(?:local\\s+)?function\\s+([a-zA-Z_0-9\\.:]+)", + "end": "^\\s*end\\b", + "inc": "\\b(if|for|while|do)\\b" + }, + ".ex": { + "start": "^\\s*(?:def|defp|defmacro)\\s+([a-zA-Z_0-9!]+)", + "end": "^\\s*end\\b", + "inc": "\\b(if|case|cond|unless|try)\\b.*\\bdo\\b" + }, + ".exs": { + "start": "^\\s*(?:def|defp|defmacro)\\s+([a-zA-Z_0-9!]+)", + "end": "^\\s*end\\b", + "inc": "\\b(if|case|cond|unless|try)\\b.*\\bdo\\b" + }, + ".adb": { + "start": "^\\s*(?:procedure|function)\\s+([a-zA-Z_0-9]+)", + "end": "^\\s*end\\s+[a-zA-Z_0-9]+;", + "inc": "\\b(if|loop|case|begin)\\b" + }, + ".ads": { + "start": "^\\s*(?:procedure|function)\\s+([a-zA-Z_0-9]+)", + "end": "^\\s*end\\s+[a-zA-Z_0-9]+;", + "inc": "\\b(if|loop|case|begin)\\b" + }, + ".au3": { + "start": "^\\s*(?:Func)\\s+([a-zA-Z_0-9]+)", + "end": "^\\s*EndFunc\\b", + "inc": "^\\s*(If|While|For|Select|Switch)\\b" + }, + ".vbs": { + "start": "^\\s*(?:Function|Sub)\\s+([a-zA-Z_0-9]+)", + "end": "^\\s*End\\s+(?:Function|Sub)\\b", + "inc": "^\\s*(If|For|While|Do)\\b", + "flags": "i" + } + }, + + "sequentialProfiles": { + ".bat": { + "start": "^\\s*:([a-zA-Z_0-9\\-]+)", + "end": "^\\s*(?:goto\\s+:eof|exit\\b)", + "stubs": ["rem todo", "rem fixme", "echo placeholder"], + "flags": "i" + }, + ".cmd": { + "start": "^\\s*:([a-zA-Z_0-9\\-]+)", + "end": "^\\s*(?:goto\\s+:eof|exit\\b)", + "stubs": ["rem todo", "rem fixme", "echo placeholder"], + "flags": "i" + }, + ".sql": { + "start": "(?:create\\s+(?:or\\s+replace\\s+)?(?:procedure|function|view))\\s+([a-zA-Z_0-9\\.]+)", + "end": "^\\s*end\\s*[a-zA-Z_0-9]*\\s*;", + "stubs": ["-- todo", "-- fixme", "return null", "raise notice"], + "flags": "i" + } + }, + + "indentationProfiles": { + ".mojo": { + "sig": "^\\s*(?:fn|def)\\s+([a-zA-Z_0-9]+)\\s*\\(", + "stubs": ["pass", "raise notimplementederror", "todo"] + }, + ".hs": { + "sig": "^([a-zA-Z_0-9]+)\\s+::\\s+.*|^\\s*([a-zA-Z_0-9]+)\\s*=", + "stubs": ["undefined", "todo", "error "] + }, + ".elm": { + "sig": "^([a-zA-Z_0-9]+)\\s+::\\s+.*|^\\s*([a-zA-Z_0-9]+)\\s*=", + "stubs": ["undefined", "todo", "error "] + } + } +} \ No newline at end of file diff --git a/mcp_config.json b/mcp_config.json new file mode 100644 index 0000000..9fde65a --- /dev/null +++ b/mcp_config.json @@ -0,0 +1,13 @@ +{ + "mcpServers": { + "mcp-drift-state-tracker": { + "command": "npx", + "args": [ + "--package", + "tsx", + "tsx", + "/absolute/path/to/mcp-drift-state-tracker/src/index.ts" + ] + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..e774059 --- /dev/null +++ b/package.json @@ -0,0 +1,37 @@ +{ + "name": "mcp-drift-state-tracker", + "version": "0.1.0", + "description": "Industrial-grade MCP server that enforces code completeness, intercepts context erosion, and neutralizes LLM laziness across multi-language repository workspaces. Zero Python — pure TypeScript + JSON-driven language profiles.", + "type": "module", + "main": "dist/index.js", + "scripts": { + "build": "tsc", + "start": "node dist/index.js", + "dev": "tsx src/index.ts", + "inspect": "npx @modelcontextprotocol/inspector tsx src/index.ts" + }, + "dependencies": { + "@modelcontextprotocol/sdk": "^1.12.1" + }, + "devDependencies": { + "@types/node": "^22.15.0", + "tsx": "^4.19.0", + "typescript": "^5.8.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "license": "AGPL-3.0", + "repository": { + "type": "git", + "url": "https://git.dcos.net/dcosnet/mcp-drift-state-tracker/" + }, + "keywords": [ + "mcp", + "model-context-protocol", + "code-completeness", + "drift-detection", + "llm-laziness", + "code-audit" + ] +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..dbcde00 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "Node16", + "moduleResolution": "Node16", + "outDir": "dist", + "rootDir": "src", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "declaration": true, + "declarationMap": true, + "sourceMap": true + }, + "include": ["src"], + "exclude": ["node_modules", "dist"] +} \ No newline at end of file