MCP Guide
Alloy includes a built-in Model Context Protocol (MCP) server that lets AI assistants interact with your projects, tickets, sprints, and time tracking directly.
Overview
The alloy-mcp server exposes Alloy’s project management capabilities as MCP tools and resources. AI assistants like Claude can create tickets, search backlogs, log time, query sprint burndown, and more — all through the standard MCP protocol.
Transport modes:
| Mode | Use case | How it works |
|---|---|---|
| stdio | Claude Desktop, Claude Code, local dev | Binary communicates over stdin/stdout (JSON-RPC) |
| HTTP | Remote servers, shared environments | TCP listener with Bearer token auth per request |
Key features:
- 67 tools covering tickets, comments, labels, tags, projects, sprints, teams, workflows, time tracking, finance, and organization management
- 15 slash commands (MCP prompts) for guided workflows — see the MCP Tools Reference for the full list
- Resource URIs for browsing projects, tickets, sprints, and user assignments
- Authenticated via Alloy API keys — the MCP server proxies requests to the Alloy API
- Protocol version:
2024-11-05
Quick Start: From Build to Working in 6 Steps
Follow these numbered steps to go from a fresh checkout to a working MCP integration.
Step 1: Build the binary
Build the alloy-mcp binary from the workspace root:
cargo build --release -p alloy-mcp
The binary is placed at target/release/alloy-mcp. Optionally, copy it somewhere on your $PATH:
cp target/release/alloy-mcp ~/.local/bin/
Step 2: Start the Alloy API server
The MCP server needs a running Alloy API to proxy requests to. Start it in a separate terminal:
cargo run --release -p alloy-api -- serve
Or if you have the binary installed:
alloy serve
See Getting Started or Deployment for full details.
Step 3: Create an API key
Via the CLI:
alloy auth api-key create --name "MCP Server"
This prints the full key (starting with alloy_live_ or alloy_test_). Copy it immediately — the full key is only shown once.
Via curl:
curl -s "$BASE_URL/api/v1/api-keys" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "MCP Server", "scopes": ["read", "write"]}' | jq .
Expected response:
{
"id": "770e8400-...",
"name": "MCP Server",
"key": "alloy_live_abc123...",
"key_prefix": "alloy_live_...",
"scopes": ["read", "write"],
"project_ids": [],
"created_at": "2026-03-28-...",
"expires_at": null
}
Save the key field — you will need it for ALLOY_API_TOKEN below.
Step 4: Test the MCP server manually
Before configuring any AI assistant, verify the binary works end-to-end on its own.
Test the stdio transport directly:
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"0.1.0"}}}' | \
ALLOY_API_URL=http://localhost:3000 \
ALLOY_API_TOKEN=alloy_live_your_key \
alloy-mcp
You should receive a JSON-RPC response containing serverInfo with name: "alloy-mcp". If you see an error instead, fix the issue before proceeding — the AI assistant configuration will not work until this step succeeds.
Test API connectivity:
curl -s http://localhost:3000/api/v1/auth/me \
-H "Authorization: Bearer $ALLOY_API_TOKEN" | jq .
You should see your user details (user_id, org_id, email, role).
Step 5: Configure your AI assistant
Choose the assistant you want to use with Alloy.
Claude Code (project-level)
Add the MCP server to your project’s .claude/mcp.json:
{
"mcpServers": {
"alloy": {
"command": "alloy-mcp",
"env": {
"ALLOY_API_URL": "http://localhost:3000",
"ALLOY_API_TOKEN": "alloy_live_your_api_key_here"
}
}
}
}
This makes Alloy available only when working inside that project directory.
Claude Code (global)
To make Alloy available across all projects, add the same configuration to ~/.claude/mcp.json instead:
{
"mcpServers": {
"alloy": {
"command": "alloy-mcp",
"env": {
"ALLOY_API_URL": "http://localhost:3000",
"ALLOY_API_TOKEN": "alloy_live_your_api_key_here"
}
}
}
}
Tip: If
alloy-mcpis not on your$PATH, use the full path in thecommandfield (e.g.,/Users/you/repos/alloy/target/release/alloy-mcp).
Claude Desktop
Add the following to your Claude Desktop MCP configuration. On macOS this is ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"alloy": {
"command": "alloy-mcp",
"env": {
"ALLOY_API_URL": "http://localhost:3000",
"ALLOY_API_TOKEN": "alloy_live_your_api_key_here"
}
}
}
}
| Field | Description |
|---|---|
command | Path to the alloy-mcp binary. Use the full path if it is not on your $PATH. |
ALLOY_API_URL | Base URL of your running Alloy API (e.g., http://localhost:3000). |
ALLOY_API_TOKEN | The API key you created above. Must start with alloy_live_ (production) or alloy_test_ (testing). |
Step 6: Restart and verify
Restart your assistant — Claude Code and Claude Desktop do not pick up MCP config changes automatically. You must restart them after editing the configuration.
- Claude Code: Close and reopen the Claude Code session (or restart the terminal)
- Claude Desktop: Quit and relaunch the application
Verify tools appear: Open Claude and check that Alloy tools are listed (e.g., create_ticket, search_tickets, ping). Try a simple command:
“Use the ping tool to check the Alloy connection”
If the tool executes and returns a response, your MCP setup is working correctly.
HTTP Transport
For remote or shared environments, run the MCP server in HTTP mode instead of stdio:
ALLOY_API_URL=http://localhost:3000 \
ALLOY_API_TOKEN=alloy_live_your_api_key_here \
alloy-mcp --http 0.0.0.0:3001
The HTTP transport:
- Listens on the specified bind address (default port
3001in the example above) - Authenticates each request via a
Bearertoken in theAuthorizationheader - Exposes OAuth 2.1 discovery metadata at
GET /.well-known/oauth-authorization-server
Connecting an MCP client to the HTTP server:
Point your MCP client at http://<host>:3001 and provide the API token as a Bearer token. Consult your client’s documentation for HTTP/SSE transport configuration.
Troubleshooting
Connection errors
| Symptom | Cause | Fix |
|---|---|---|
| “connection refused” | Alloy API not running | Start the API server first (alloy serve or cargo run -p alloy-api -- serve) |
| “connection refused” on port 3001 | HTTP-mode MCP server not running | Start it with alloy-mcp --http 0.0.0.0:3001 |
| Timeout or hanging | API URL wrong or unreachable | Check ALLOY_API_URL — it must match the running server’s address and port |
Authentication errors
| Symptom | Cause | Fix |
|---|---|---|
| “invalid API token” | Bad or missing ALLOY_API_TOKEN | Regenerate the key; ensure it starts with alloy_live_ or alloy_test_ |
| “unauthorized” / 401 | Token expired or revoked | Create a new API key and update your config |
| “forbidden” / 403 | Token missing required scopes | Recreate the key with "scopes": ["read", "write"] |
Tools not appearing
| Symptom | Cause | Fix |
|---|---|---|
| No Alloy tools listed | Config file not loaded | Restart Claude Desktop / Claude Code after saving the config |
| No Alloy tools listed | JSON syntax error in config | Validate the JSON (e.g., jq . < .claude/mcp.json) — a trailing comma or missing quote will silently fail |
| No Alloy tools listed | Wrong config file location | Claude Code uses .claude/mcp.json (project) or ~/.claude/mcp.json (global); Claude Desktop uses ~/Library/Application Support/Claude/claude_desktop_config.json on macOS |
| Tools listed but calls fail | Binary not found | Use the full absolute path in the command field, or verify alloy-mcp is on your $PATH with which alloy-mcp |
| Tools listed but calls fail | Binary is stale / outdated | Rebuild with cargo build --release -p alloy-mcp and restart the assistant |
Debugging MCP communication
To see raw JSON-RPC messages, run the MCP server manually and inspect its output:
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' | \
ALLOY_API_URL=http://localhost:3000 \
ALLOY_API_TOKEN=alloy_live_your_key \
alloy-mcp 2>mcp-stderr.log
Check mcp-stderr.log for diagnostic messages. If the server starts but returns errors for tool calls, the issue is likely with the API server or API key — re-run Step 4 to isolate the problem.