Simplified MCP server for Latitude.so prompt management - 8 focused tools for push, pull, run, and manage prompts
npm install latitude-mcp-server> AI-powered prompt management for Latitude.so via Model Context Protocol
Manage PromptL prompts directly from Claude, Windsurf, or any MCP client. Features intelligent validation, dynamic tool descriptions, and git-style versioning.


---
- š¤ Smart Validation - Client-side PromptL validation with AST-powered error messages
- š Dynamic Descriptions - Tools show available prompts and their parameters automatically
- š Full Sync - Push/pull with automatic conflict resolution
- šÆ Atomic Operations - Validate ALL before pushing ANY (all-or-nothing)
- š 52 Doc Topics - Comprehensive PromptL syntax guide with semantic search
- š·ļø Git-Style Versioning - Name your changes like commits (feat/add-auth, fix/typo)
- ā” Zero Config - Just set LATITUDE_API_KEY and go
---
``bash`
npm install -g latitude-mcp-server
Set environment variables:
`bash`
export LATITUDE_API_KEY="your-api-key"
export LATITUDE_PROJECT_ID="your-project-id"
Get your API key from Latitude Settings.
Add to your MCP client config (e.g., Claude Desktop):
`json`
{
"mcpServers": {
"latitude": {
"command": "npx",
"args": ["latitude-mcp-server"],
"env": {
"LATITUDE_API_KEY": "your-api-key",
"LATITUDE_PROJECT_ID": "your-project-id"
}
}
}
}
---
| Tool | Type | Description |
|------|------|-------------|
| list_prompts | Read | List all prompts in LIVE |get_prompt
| | Read | Get full prompt content by name |run_prompt
| | Execute | šÆ Dynamic: Shows all prompts with their parameters |push_prompts
| | Write | š FULL SYNC: Replace ALL prompts (deletes extras) |pull_prompts
| | Read | š FULL SYNC: Download all prompts (deletes local first) |add_prompt
| | Write | šÆ Dynamic: Add/update prompts (shows available prompts) |docs
| | Read | Get documentation (52 topics, semantic search) |
Dynamic Tool Descriptions - The MCP server updates tool descriptions in real-time:
- run_prompt shows: "my-prompt" (params: name, email, company)add_prompt
- shows: "Available prompts (10): prompt-a, prompt-b, ..."
Your AI assistant sees exactly what prompts exist and what parameters they need!
---
`bash`Pull all prompts from LIVE to start local development
pull_prompts({ outputDir: "./prompts" })Downloads 10 files to ./prompts/
Deletes any existing local .promptl files first (FULL SYNC)
What you see:
`
ā
Prompts Pulled from LIVE
Directory: /Users/you/project/prompts
Deleted: 0 existing files
Written: 10 files
Files:
- cover-letter-generate.promptl
- sentiment-analyzer.promptl
...
Tip: Edit files locally, then use add_prompt to push changes.`
`bash---The tool description shows you what prompts already exist!
add_prompt({
prompts: [{
name: "email-writer",
content:
provider: openai
model: gpt-4o
---
Write email to {{ recipient }} about {{ topic }}`
}],
versionName: "feat/add-email-writer" # Optional git-style naming
})
Dynamic Description Shows:
`
Add or update prompt(s) in LIVE without deleting others.
Available prompts (10): cover-letter-generate, sentiment-analyzer, ...
`
Result:
`
ā
Prompts Added to LIVE
Summary:
- Added: 1
- Updated: 0
Added:
- email-writer
Current LIVE prompts (11): cover-letter-generate, ..., email-writer
`
`bash`The tool description shows you what parameters each prompt needs!
run_prompt({
name: "email-writer",
parameters: {
recipient: "Alice",
topic: "project update"
}
})
Dynamic Description Shows:
`
Execute a prompt with parameters.
Available prompts (11):
- cover-letter-generate (params: job_details, career_patterns, company_name)
- email-writer (params: recipient, topic)
- sentiment-analyzer (no params)
...
`
Result:
`
ā
Prompt Executed
Prompt: email-writer
Parameters:
{
"recipient": "Alice",
"topic": "project update"
}
Response:
Subject: Project Update
Dear Alice,
I wanted to share an update on our project...
Tokens: 245 total
`
`bash---Try to add a prompt with nested tags (invalid PromptL)
add_prompt({
prompts: [{
name: "broken",
content:
model: gpt-4
---`
}]
})
Validation Error (Before ANY API Call):
`
ā Validation Failed - No Changes Made
1 prompt(s) have errors. Fix all errors before pushing.
Error: Message tags cannot be inside of another message
Root Cause: Message/role tags (, , , ) cannot be nested.
Location: Line 4, Column 7
Code Context:
`
2: model: gpt-4
3: ---
4: Nested! ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
`
Fix: Move the nested tag outside its parent. Use code block (`yaml) for examples.Action Required: Fix the errors above, then retry.
`$3
`bash
Push local prompts to LIVE - deletes remote prompts not in your folder
push_prompts({
folderPath: "/absolute/path/to/prompts",
versionName: "feat/initial-prompts" # Optional
})
`Result:
`
ā
Prompts Pushed to LIVESummary:
- Added: 3
- Modified: 0
- Deleted: 8 # Removed old prompts not in your list
Current LIVE prompts (3): prompt-a, prompt-b, prompt-c
`---
š Documentation Topics (52)
$3
overview, structure, variables, conditionals, loops, references, tools, chains, agents, techniques, agent-patterns, mocking$3
config-basics, config-generation, config-json-output, config-advanced, providers-openai, providers-anthropic, providers-google, providers-azure$3
messages-roles, messages-multimodal$3
tools-builtin, tools-custom, tools-schema, tools-orchestration$3
technique-role, technique-few-shot, technique-cot, technique-tot, technique-react, technique-self-consistency, technique-constitutional, technique-socratic, technique-meta, technique-iterative, technique-step-back, technique-rag$3
recipe-classification, recipe-extraction, recipe-generation, recipe-chatbot, recipe-rag, recipe-analysis, recipe-moderation, recipe-support$3
conversation-history, guide-debugging, guide-safety, guide-performance, guide-testing, guide-versioning---
š ļø Development
$3
`bash
npm run build # Compiles TypeScript to dist/
`$3
`bash
List all tools
npx @modelcontextprotocol/inspector \
-e LATITUDE_API_KEY=your-key \
-e LATITUDE_PROJECT_ID=your-id \
--cli node dist/index.js \
--method tools/listTest list_prompts
npx @modelcontextprotocol/inspector \
-e LATITUDE_API_KEY=your-key \
-e LATITUDE_PROJECT_ID=your-id \
--cli node dist/index.js \
--method tools/call \
--tool-name list_promptsTest add_prompt with file
npx @modelcontextprotocol/inspector \
-e LATITUDE_API_KEY=your-key \
-e LATITUDE_PROJECT_ID=your-id \
--cli node dist/index.js \
--method tools/call \
--tool-name add_prompt \
--tool-arg 'filePaths=["./prompts/test.promptl"]'Test from npm package
npx @modelcontextprotocol/inspector \
-e LATITUDE_API_KEY=your-key \
-e LATITUDE_PROJECT_ID=your-id \
--cli npx -y latitude-mcp-server@3.1.0 \
--method tools/call \
--tool-name list_prompts
`$3
`bash
Build and run
npm run build
node dist/index.jsWith environment variables
LATITUDE_API_KEY=xxx LATITUDE_PROJECT_ID=yyy node dist/index.jsWatch mode (requires nodemon)
npm install -g nodemon
nodemon --watch src --exec "npm run build && node dist/index.js"
`---
Project Structure
`
latitude-mcp-server/
āāā src/
ā āāā docs/ # Documentation system (52 topics)
ā ā āāā types.ts # Type definitions
ā ā āāā metadata.ts # Search metadata
ā ā āāā help.ts # Help content
ā ā āāā core-syntax.ts # Core PromptL syntax (12 topics)
ā ā āāā phase1.ts # Tier 1 topics (8)
ā ā āāā phase2.ts # Tier 2 topics (13)
ā ā āāā phase3.ts # Tier 3 topics (6)
ā ā āāā techniques.ts # Prompting techniques (8)
ā ā āāā recipes.ts # Use case recipes (5)
ā ā āāā index.ts # DOCS_MAP + functions
ā āāā utils/ # Utilities
ā ā āāā config.util.ts # Environment config
ā ā āāā logger.util.ts # Logging
ā āāā api.ts # Latitude API client
ā āāā docs.ts # Documentation exports
ā āāā index.ts # MCP server entry
ā āāā server.ts # MCP server setup
ā āāā tools.ts # 8 MCP tools
ā āāā types.ts # Type definitions
āāā scripts/
ā āāā ensure-executable.js
āāā .gitignore
āāā package.json
āāā tsconfig.json
āāā README.md
`---
Environment Variables
| Variable | Required | Description |
|----------|----------|-------------|
|
LATITUDE_API_KEY | Yes | Your Latitude API key |
| LATITUDE_PROJECT_ID | Yes | Your project ID |
| DEBUG | No | Enable debug logging |---
PromptL Syntax Overview
PromptL is a templating language for AI prompts:
`promptl
---
provider: OpenAI
model: gpt-4o
temperature: 0.7
schema:
type: object
properties:
answer:
type: string
required: [answer]
---
You are a helpful assistant.
{{ question }}
`Key Features:
- YAML config header (provider, model, temperature)
- Message tags (
, , )
- Variables ({{ name }})
- Conditionals ({{ if }}, {{ else }})
- Loops ({{ for item in items }})
- Tools (function calling)
- Chains (multi-step )
- Agents (autonomous type: agent)Use
docs({ action: "get", topic: "overview" }) for complete guide.---
š Tool Reference
$3
List all prompts in LIVE version.
Returns: Array of prompt names with project ID
Example:
`javascript
list_prompts()
// Returns: cover-letter-generate, sentiment-analyzer, email-writer (10 total)
`---
$3
Get full prompt content by name.
Parameters:
-
name (string) - Prompt nameReturns: Full PromptL content with config and messages
Example:
`javascript
get_prompt({ name: "email-writer" })
// Returns full .promptl content
`---
$3
šÆ Dynamic: Execute a prompt. Tool description shows all prompts with their parameters!
Parameters:
-
name (string) - Prompt name
- parameters (object, optional) - Input parametersReturns: AI response with token usage
Dynamic Description:
`
Available prompts (10):
- email-writer (params: recipient, topic)
- sentiment-analyzer (no params)
- cover-letter-generate (params: job_details, career_patterns, company_name)
`Example:
`javascript
run_prompt({
name: "email-writer",
parameters: { recipient: "Alice", topic: "update" }
})
`---
$3
šÆ Dynamic: Add or update prompts without deleting others. Tool description shows available prompts!
Behavior: If prompt exists ā overwrites. If new ā adds. Never deletes other prompts.
Parameters (choose one):
Option A - Direct content:
-
prompts (array) - Array of { name, content }Option B - From files:
-
filePaths (array) - Array of paths to .promptl filesCommon:
-
versionName (string, optional) - Git-style name like feat/add-auth or fix/typoReturns: Summary of added/updated prompts
Example:
`javascript
add_prompt({
filePaths: ["./prompts/new-prompt.promptl"],
versionName: "feat/add-new-prompt"
})
`---
$3
š FULL SYNC: Replace ALL prompts in LIVE. Deletes remote prompts not in your list.
Use for: Initial setup, complete sync, resetting LIVE to match local.
Parameters (choose one):
Option A - Direct content:
-
prompts (array) - Array of { name, content }Option B - From files:
-
filePaths (array) - Array of paths to .promptl filesCommon:
-
versionName (string, optional) - Git-style name like feat/initial-setupReturns: Summary of added/modified/deleted prompts
Example:
`javascript
push_prompts({
filePaths: ["./prompts/prompt-a.promptl", "./prompts/prompt-b.promptl"],
versionName: "feat/complete-rewrite"
})
`---
$3
š FULL SYNC: Download all prompts from LIVE. Deletes existing local
.promptl files first.Use for: Initial clone, resetting local to match LIVE.
Parameters:
-
outputDir (string, optional) - Output directory (default: ./prompts)Returns: List of downloaded files
Example:
`javascript
pull_prompts({ outputDir: "./my-prompts" })
`---
$3
Access comprehensive PromptL documentation (52 topics).
Parameters:
-
action (string) - "help" (overview), "get" (topic), or "find" (search)
- topic (string, optional) - Topic name for "get"
- query (string, optional) - Search query for "find"Returns: Documentation content
Examples:
`javascript
docs({ action: "help" }) // Overview
docs({ action: "find", query: "json output" }) // Semantic search
docs({ action: "get", topic: "chains" }) // Specific topic
`---
ā
Validation Features
$3
All write operations (
add_prompt, push_prompts) validate prompts before making API calls using the official promptl-ai library.Benefits:
- ā” Fast feedback - No wasted API calls
- šÆ Precise errors - Exact line and column numbers
- š Code frames - See surrounding context with
^~~~ pointer
- š¤ LLM-actionable - Errors include root cause and fix suggestions$3
Validate ALL, push ALL or NOTHING:
`javascript
// Trying to push 10 prompts, but 1 has an error
add_prompt({
filePaths: [
"./prompts/valid-1.promptl",
"./prompts/valid-2.promptl",
"./prompts/BROKEN.promptl", // Has nested tags
// ... 7 more valid prompts
]
})// Result: NOTHING is pushed
// Error shows exactly what's wrong in BROKEN.promptl
// Fix the error, retry ā all 10 push successfully
`$3
`
ā Validation Failed - No Changes Made1 prompt(s) have errors.
$3
Error Code: message-tag-inside-message
Error: Message tags cannot be inside of another message
Root Cause: Message/role tags cannot be nested inside each other.
Location: Line 107, Column 1
Code Context:
`
105: ## EXAMPLES
106:
107: ^~~~~~~~~~~~
108: questions:
109: - id: q1
`
Fix: Move the nested tag outside its parent. Use code block (`yaml) instead.
`$3
-
message-tag-inside-message - Nested role tags
- content-tag-inside-content - Nested content tags
- config-not-found - Missing YAML frontmatter
- invalid-config - Malformed YAML
- unclosed-block - Missing closing tag
- variable-not-defined - Undefined variable
- invalid-tool-call-placement - Tool call outside
- ...and more from official promptl-ai compiler---
š Migration Guide (v2 ā v3)
$3
| Old Tool (v2) | New Tool (v3) | Notes |
|---------------|---------------|-------|
|
append_prompts | add_prompt | Always overwrites if exists (no overwrite param needed) |
| replace_prompt | add_prompt | Same behavior, unified tool |Migration:
`javascript
// OLD (v2)
append_prompts({ filePaths: [...], overwrite: true })
replace_prompt({ filePath: "./prompt.promptl" })// NEW (v3)
add_prompt({ filePaths: [...] }) // Always overwrites if exists
`---
š§ Troubleshooting
$3
Problem: Prompt fails with nested tag error
Solution: The error shows exact location with code frame:
`
Error Code: message-tag-inside-message
Location: Line 4, Column 7
Code Context:
4: Nested!
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Fix: Move the nested tag outside its parent.
`Follow the fix suggestion - errors are LLM-actionable!
$3
Problem:
push_prompts reports no changesCause: All prompts are already up to date (content matches LIVE)
Solution: This is normal - no action needed
$3
Good:
-
feat/add-sentiment-analyzer
- fix/typo-in-greeting
- refactor/simplify-prompts
- docs/update-examplesAvoid:
-
test (too vague)
- update (what was updated?)
- v1.2.3 (use semantic versioning elsewhere)$3
Problem: Tool descriptions show old prompt list
Cause: Cache not refreshed (30s TTL)
Solution: Wait 30 seconds or restart MCP server
---
Contributing
1. Fork the repository
2. Create a feature branch
3. Make your changes
4. Run
npm run build to verify
5. Submit a pull request---
License
ISC License - see LICENSE file for details
---
Links
- Latitude Platform
- Latitude Documentation
- Model Context Protocol
- npm Package
- GitHub Repository
---
Support
- Issues: GitHub Issues
- Documentation: Use
docs({ action: "help" })` tool---
Built with ā¤ļø for the MCP ecosystem