Lattice MCP Server
Automates Lattice HR objectives (create, update, delete, list) via browser session replay. No API key required — authenticates through SSO and persists the session for headless Playwright reuse.
Prerequisites
- Python 3.10+
- Chrome/Chromium (for SSO login)
- A display environment (local machine or X-forwarded) for initial login
Installation
pip install lattice-mcp
playwright install chromium
Authentication
The server uses a saved Playwright browser session (~/.config/lattice/browser-state.json). You must log in once via SSO to create it.
Option A: Local machine with a display
lattice ui login [--hostname <your-company>.latticehq.com]
If --hostname is omitted, it falls back to the LATTICE_WEB_HOSTNAME environment variable (see Configuration).
A Chromium window opens — complete your SSO login. The window closes automatically once authenticated and the session is saved. The session is reusable until it expires on Lattice's side (typically days to weeks).
Option B: Headless server (attach to running Chrome)
# On a machine with a display, start Chrome with remote debugging:
google-chrome --remote-debugging-port=9223 --user-data-dir=/tmp/chrome-lattice --no-first-run &
# Complete SSO in that browser, then capture the session:
lattice ui login --cdp-url http://127.0.0.1:9223
Option C: Silent headless re-login (after first login)
lattice ui login --headless
Reuses the stored browser state: even if the Lattice session has expired, the saved IdP session cookies (e.g. Microsoft Entra) usually allow the SSO to complete silently — no window, no password, no MFA. Works until the IdP's own session expires (often weeks), then fall back to Option A/B. Whether the silent hop is permitted depends on your IdP tenant's conditional-access policies.
Session expiry
If tools return "Session expired", re-run lattice ui login — or let the agent call the lattice_ui_login MCP tool, which tries the silent headless refresh first and only opens a login window if that fails (you complete the SSO yourself).
Configuration
All configuration is via environment variables — no code changes needed to point at your own Lattice tenant:
| Variable | Purpose | Default |
|---|---|---|
LATTICE_WEB_HOSTNAME |
Your Lattice tenant, e.g. acme.latticehq.com |
c3.latticehq.com |
LATTICE_USER_ENTITY_ID |
Your Lattice user entity UUID — the default owner for lattice_objectives |
unset (tools require an explicit owner_id) |
LATTICE_CONFIG_DIR |
Where credentials and the browser session are stored | ~/.config/lattice |
lattice ui login also accepts --hostname directly (takes precedence over the env var). The hostname is not saved with the session — the MCP server re-reads LATTICE_WEB_HOSTNAME on every call, so set it wherever the server is launched (see below).
To find your user entity ID: open any Lattice page filtered to your objectives and copy the UUID from the URL (ownerEntityIdsFilter=...), or inspect a GraphQL response in your browser's devtools.
Notifications (ntfy)
Cron jobs and agents can push alerts to your phone via ntfy:
lattice notify --setup # generate your personal topic + show subscribe info (QR)
lattice notify --test # send a test push
lattice notify "message" --title "optional title"
lattice notify --show # re-print topic / URL / QR anytime
The first use generates a per-user topic like lattice-<user>-<random12> and stores it in ~/.config/lattice/config.json. The random suffix is the secret — on public ntfy servers the topic name is the only access control, so don't shorten it or share it.
A successful manual lattice ui login shows the subscription info (topic, URL, QR) automatically, so new users see it at onboarding without a separate step. The ASCII QR is also saved to ~/.config/lattice/ntfy-qr.txt for when the terminal output isn't usable (e.g. agent-mediated setup — open the file in any editor and scan it). If a send auto-generates a topic (nothing configured yet), it prints a warning that nobody is subscribed.
Overrides (env beats config file):
| env | config.json key | default | |
|---|---|---|---|
| Topic | LATTICE_NTFY_TOPIC |
ntfy_topic |
generated on first use |
| Server | LATTICE_NTFY_SERVER |
ntfy_server |
https://ntfy.sh |
Install the qr extra (pip install lattice-mcp[qr]) for a scannable terminal QR code during setup:
$ lattice notify --show
Topic: lattice-example-abc123xyz789
URL: https://ntfy.sh/lattice-example-abc123xyz789
█▀▀▀▀▀▀▀████▀▀▀██▀▀▀▀▀█▀▀██▀▀▀▀▀▀▀█
█ █▀▀▀█ █▀▄▀▄█ ▄ █ ▀█▄█▄▀▄█ █▀▀▀█ █
█ █ █ █ █ ▄ ▀▄ ▄█▀▄▄ ▄▄ █ █ █ █
█ ▀▀▀▀▀ █ ▄▀▄ █ ▄ ▄ █ █▀█▀█ ▀▀▀▀▀ █
█▀█▀▀▀▀▀█▄█ █▄▀▀ ▀▀███▄ ▀ █▀▀▀▀▀███
█ ▄█ ▄ ▀▄ ▀█ ██▀ █ ▄▄ █▄▄█ ▄▀▄ ▀▄█
█▄▄█▄█▀▀ ▀▄ █▄▄▄█▀█▄ ▄▀▄▀██ ▄▄██
█ ▄▀ ▄ ▀ █ ▀ ▀▀ ▄▄██▀▄▀▄▄ █▀█▄ ▄█
█▀██▀ ▀▀▀▄▄ █▄ █▄▀▀ ▄█▀▄ ▄ ▀▄▄█▀█
█▄█▀▄ ▄▀ ▀ █▄▄▀▀ ▄▄▄█▀▄▀█ ▀▄ ▀▄█
█▀█▄ ▄▀▀ ▄▄▀█ █ ▀▄▄█ ▀▀▄█ █▄ ▄ ▀█
█ █▄ ▀ ▀ ▀▄▀ ▄█ ▀▄▄█▀█▀▄▄ ▀▀▄▀▄█
█ █▀ ▀ ▀▀▄▄▄ ▀█ █▀██▀▄ ▄▀▀ ▀▀▄▀▀█
█▀▀▀▀▀▀▀█▄▀▄█ ▄▀▄█ ▄ █▀ █▀█ █ █▄█
█ █▀▀▀█ █ ▀███▄ ▄██▀██ ▄▄ ▀▀▀ ▄ ██
█ █ █ █ ▄▄█▀█▄▄██▀▄▀ ▀ ▀▀▄▀ █▄█
█ ▀▀▀▀▀ █▀ ██ ▀█ ▀█ ▄▄▀▄▀█ ▀▄▀▄▀██
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
Scan with your phone to subscribe in the ntfy app.
MCP Server Setup (Claude Code)
Add to your project's .mcp.json:
{
"mcpServers": {
"lattice": {
"command": "lattice-mcp",
"env": {
"LATTICE_WEB_HOSTNAME": "<your-company>.latticehq.com",
"LATTICE_USER_ENTITY_ID": "<your-user-entity-uuid>"
}
}
}
}
Restart Claude Code to load the server. The tools appear as lattice_* in your session.
Available Tools
| Tool | Description |
|---|---|
lattice_session_status |
Check if the browser session is active |
lattice_ui_login |
Open a browser window for SSO login (requires a display; the user completes the login) |
lattice_notify |
Send a push notification to the user via ntfy |
lattice_objectives |
List active objectives for a user (defaults to you) |
lattice_create_objective |
Create a new objective (title, optional priority/due date) |
lattice_update_objective |
Post a status update + comment to an objective |
lattice_delete_objective |
Delete an objective by entityId |
lattice_scrape |
Scrape any Lattice page and return visible text |
Example usage (via Claude Code)
> list my lattice objectives
> create a lattice objective titled "Ship feature X"
> update objective <entityId> status green comment "Merged PR, deploying tomorrow"
> delete objective <entityId>
Multi-server workflow (with Jira MCP)
If you also have a Jira MCP server in your session, you can chain them:
> fetch PLAT-0000 and PLAT-0001 from jira, then create lattice objectives from their summaries
Claude calls the Jira server to get ticket details, then calls lattice_create_objective for each — no glue code needed.
How It Works
- Tools launch headless Chromium with the saved session cookies
- Navigate to the relevant Lattice page
- Interact with the UI (fill forms, click buttons) via Playwright
- GraphQL mutations fire as a side-effect of the UI interaction
- Cloudflare passes because the session includes valid clearance cookies
There is no direct API access — Lattice does not issue API keys to non-admins. See DESIGN.md for the full decision log.
Troubleshooting
| Problem | Fix |
|---|---|
| "No browser session" | Run lattice ui login |
| "Session expired" | Re-run lattice ui login |
| Cloudflare blocks (403) | Session stale — re-login to get fresh cf_clearance cookies |
| Tool times out | Lattice page may be slow; try again |
| Create succeeds but objective not visible | Check the "All time" filter on /goals — it may default to current quarter |
Metadata
Release files for lattice-mcp 0.1.15
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| lattice_mcp-0.1.15.tar.gz | 27.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| lattice_mcp-0.1.15-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 48.2 kB
Release files / lattice_mcp-0.1.15.tar.gz
| Download URL | lattice_mcp-0.1.15.tar.gz |
|---|---|
| Size | 27.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ccf3774ae34486f6517bfc3cc273f0e38bf2432cd53d4723f4d599e7503f2ebf
|
|
BLAKE2b-256 checksum How to use checksums |
c0a98abb8d611a4a2b6e5b69ce15c6bcfa161a784ce6d0c691d63a6adca2dda4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.13
|
Release files / lattice_mcp-0.1.15-py3-none-any.whl
| Download URL | lattice_mcp-0.1.15-py3-none-any.whl |
|---|---|
| Size | 21.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
583fbd9299e133f24529e22616447ba18a0b998f0128f67ebe239721a124beac
|
|
BLAKE2b-256 checksum How to use checksums |
6e976d5c0cff4d4108238e51e4617d352018e3a29c6020bae57f3752c994ed7c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.13
|