@lokal-id/mcp
[npm]
[License: MIT]
An MCP server that makes AI agents Indonesia-ready: accurate Kemendagri region and postal code data, holidays and working days, NIK/NPWP/phone validation, Rupiah, and Samaran, which lets an agent read production files (CSV, Excel, logs) with Indonesian personal data replaced by stable placeholders, then write results with the real values restored, locally.
Part of Lokal · Bahasa Indonesia
Install
Claude Code: install the Lokal plugin, which bundles this server with the skills and the Samaran Guard hook:
Cursor, Claude Desktop, Windsurf (.cursor/mcp.json, claude_desktop_config.json, ~/.codeium/windsurf/mcp_config.json):
VS Code (.vscode/mcp.json):
Codex CLI (~/.codex/config.toml):
The file tools can only access LOKAL_ROOT, which defaults to CLAUDE_PROJECT_DIR and then to the working directory.
Tools
parse_alamat, parse_nik, parse_phone, and validate_npwp also take placeholders from read_file_masked ([ADDRESS_3], [NIK_1]): the real value is read on your machine, and the street, RT/RW, and birth date come back as placeholders.
Samaran Guard
lokal-mcp guard is a hook for Claude Code (UserPromptSubmit, and PreToolUse for Read|Grep|Bash|PowerShell), Codex CLI, Cursor, and Gemini CLI. It holds prompts that contain NIK, bank account, or health data, blocks commands that would print a personal data file into the conversation, pointing the agent to read_file_masked instead, and asks before photos of documents and scanned PDFs are read. The Lokal plugin sets it up for Claude Code; see the Lokal README for the other agents.
SAMARAN_GUARD=strict makes it fail closed: what it cannot check is blocked, including a guard error, a file it cannot read, output from beyond the first 5 MB of a big file, a Grep over more than 300 data files, and a check that runs longer than 7 seconds. One-liners such as python -c and node -e that name a data file with personal data are blocked like cat. It is still not a sandbox; see Defense in depth.
Your own data types
.samaran.json at the project root adds rules for formats Samaran cannot know, and values it must never mask. The file tools, the guard, lokal-mcp scan, and the proxy read it; restart the server after changing it. A broken file makes the file tools fail rather than mask less.
Policy and audit
.samaran.json can also set an action per type: "policy": { "HEALTH": "block", "FINANCIAL": "allow", "PASSPORT": "route" }. block makes read_file_masked refuse a file and the proxy refuse a request; allow leaves a type unmasked; route sends proxied requests to a local model ("route": { "openai": "http://127.0.0.1:11434/v1", "model": "llama3.2" }). "audit": true writes one JSON line per decision, with counts and never values, to .lokal/audit.jsonl; lokal-mcp audit summarizes it. "vaultTtlMinutes": 60 makes the server forget the real values after an hour without use. "guard": "strict" turns on the strict guard for everyone in the repository. "ner": true adds Lokal's NER model for names without a label or cue, such as "saya di chat sama rianto surya", to read_file_masked, scan_pii, and the proxy; install it next to the server with npx -y -p @lokal-id/mcp -p @lokal-id/ner lokal-mcp (see @lokal-id/ner). See the Lokal README.
lokal-mcp init --profile personal|team|strict [--dry-run] writes .samaran.json, .samaranignore, and for teams a GitHub workflow; lokal-mcp check validates the configuration and explains what it does.
Kembaran
lokal-mcp kembaran prod.sql export.csv -o staging/ [--secret <text>] [--keep FINANCIAL] [--keep-birth-date] [--dry-run] copies text files with every person replaced by a realistic stand-in, consistent across the files. See the Lokal README.
Lokal Scan
lokal-mcp scan --staged (pre-commit) or lokal-mcp scan --diff origin/main (CI) fails when a commit or pull request adds Indonesian personal data, and shows each value partially masked. lokal-mcp scan [path…] checks whole files. There is a GitHub Action too: uses: lokal-id/[email protected]. See the Lokal README.
Remote (HTTP) mode
lokal-mcp serve --http --port 3000 serves the data tools over Streamable HTTP at /mcp, for ChatGPT and Claude.ai connectors. The file tools are not available in this mode.
Samaran Proxy
lokal-mcp proxy is an OpenAI- and Anthropic-compatible endpoint for apps: it masks Indonesian personal data in every request and restores it in the response, streaming and tool calls included.
Then use OpenAI(base_url="http://127.0.0.1:8787/v1") or Anthropic(base_url="http://127.0.0.1:8787"). Requests with images or files inside are forwarded with x-samaran-status: partial, since they cannot be checked; --strict refuses them. See the Lokal README.
License
MIT. The library is @lokal-id/core.