Skip to content

HelpDesk MCP Server

The HelpDesk MCP (Model Context Protocol) server enables LLMs like Claude to create tickets, tasks, and interact with your HelpDesk system through natural language.

Overview

The MCP server is deployed as a Firebase Cloud Function (Gen 2, running on Cloud Run) and supports both HTTP and SSE transports. It exposes the following tools:

ToolDescription
create_ticketCreate a new support ticket
create_taskCreate a new task
list_ticketsList tickets with optional status filter
get_ticketGet details of a specific ticket
search_ticketsSearch tickets by keyword
add_ticket_replyAdd a reply to a ticket
list_tasksList tasks with optional status filter

Getting an API Key

Users can generate their own API keys via the MCP Auth Portal:

  1. Visit https://your-helpdesk-url/mcp
  2. Sign in with Google
  3. Click “Create New Key”
  4. Enter a name for your key (e.g., “Claude Desktop”)
  5. Select your tenant
  6. Copy the key immediately - it won’t be shown again!

The portal also shows:

  • All your existing API keys
  • Usage statistics (last used, total calls)
  • Ability to delete keys

Option 2: Legacy Static Key (Admin Only)

For backward compatibility, admins can set a shared API key:

Terminal window
# Generate a random API key
openssl rand -hex 32
# Set it as a Firebase secret
firebase functions:secrets:set MCP_API_KEY

Note: User-generated keys (starting with hdsk_) are preferred as they:

  • Are tied to individual users for accountability
  • Can be revoked without affecting other users
  • Track usage per key
  • Automatically associate with the correct tenant

Setup

1. Deploy the Function

Deploy the MCP function to Firebase:

Terminal window
cd /path/to/HelpDesk
./deploy.sh --functions-only

Or deploy just the MCP function:

Terminal window
firebase deploy --only functions:mcp

3. Get the Function URL

After deployment, note the function URL. It will be displayed as:

Function URL (mcp(us-central1)): https://mcp-XXXXXX-uc.a.run.app

The actual URL for this project is:

https://mcp-a5kjn6gt4q-uc.a.run.app

Using with Claude Code

Claude Code supports MCP servers natively via SSE transport. Add a .mcp.json file to your project root:

{
"mcpServers": {
"helpdesk": {
"type": "sse",
"url": "https://mcp-a5kjn6gt4q-uc.a.run.app/sse",
"headers": {
"X-API-Key": "your-api-key-here",
"X-Tenant-ID": "default"
}
}
}
}

Or add it via the CLI:

Terminal window
claude mcp add --transport sse --scope project helpdesk https://mcp-a5kjn6gt4q-uc.a.run.app/sse \
--header "X-API-Key: your-api-key-here" \
--header "X-Tenant-ID: default"

After adding, restart Claude Code and verify the connection:

  • Type /mcp to see connected servers
  • The helpdesk server should show as “connected”

Important: Cloud Run IAM Settings

The MCP Cloud Run service must allow unauthenticated invocations:

  1. Go to Cloud Run console: https://console.cloud.google.com/run
  2. Click on the mcp service
  3. Go to the Security tab
  4. Disable “Use IAM to authenticate incoming requests”

This allows Claude Code to connect while the MCP server still validates API keys in headers.

Using with Claude Desktop

Add the following to your Claude Desktop configuration file:

macOS: ~/Library/Application Support/Claude/claude_desktop_config.json Windows: %APPDATA%\Claude\claude_desktop_config.json

{
"mcpServers": {
"helpdesk": {
"command": "npx",
"args": [
"mcp-remote-client",
"https://mcp-a5kjn6gt4q-uc.a.run.app"
],
"env": {
"MCP_API_KEY": "your-api-key-here",
"MCP_TENANT_ID": "default"
}
}
}
}

Note: You’ll need an MCP remote client that supports HTTP transport. Alternatively, you can use the server directly via HTTP or SSE.

Direct HTTP Usage

You can also call the MCP server directly via HTTP:

Initialize Connection

Terminal window
curl -X POST https://mcp-a5kjn6gt4q-uc.a.run.app \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-H "X-Tenant-ID: default" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {}
}'

List Available Tools

Terminal window
curl -X POST https://mcp-a5kjn6gt4q-uc.a.run.app \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-d '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/list",
"params": {}
}'

Create a Ticket

Terminal window
curl -X POST https://mcp-a5kjn6gt4q-uc.a.run.app \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-H "X-Tenant-ID: default" \
-d '{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "create_ticket",
"arguments": {
"title": "Printer not working",
"description": "The office printer on the 3rd floor is showing an error code E-501",
"priority": "Medium",
"name": "John Doe",
"email": "john@example.com"
}
}
}'

Create a Task

Terminal window
curl -X POST https://mcp-a5kjn6gt4q-uc.a.run.app \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-H "X-Tenant-ID: default" \
-d '{
"jsonrpc": "2.0",
"id": 4,
"method": "tools/call",
"params": {
"name": "create_task",
"arguments": {
"title": "Order new printer cartridges",
"description": "Order replacement cartridges for the 3rd floor printer",
"priority": 2,
"deadline": "next week"
}
}
}'

Search Tickets

Terminal window
curl -X POST https://mcp-a5kjn6gt4q-uc.a.run.app \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-H "X-Tenant-ID: default" \
-d '{
"jsonrpc": "2.0",
"id": 5,
"method": "tools/call",
"params": {
"name": "search_tickets",
"arguments": {
"query": "printer",
"limit": 5
}
}
}'

Multi-Tenant Support

The MCP server supports multi-tenancy. Pass the tenant ID in the X-Tenant-ID header:

Terminal window
-H "X-Tenant-ID: your-tenant-id"

If not specified, it defaults to "default".

Tool Schemas

create_ticket

ParameterTypeRequiredDescription
titlestringYesBrief title describing the issue
descriptionstringYesDetailed description
prioritystringNoUrgent, High, Medium, Low, or Background (default: Medium)
namestringYesName of the submitter
emailstringYesEmail of the submitter
phonestringNoPhone number
locationstringNoRCL, RCL-EH, My Home, or Other (default: Other)

create_task

ParameterTypeRequiredDescription
titlestringYesBrief title for the task
descriptionstringYesDetailed description
priorityintegerNo1-5 where 1 is highest (default: 3)
deadlinestringYesISO date or “today”, “tomorrow”, “next week”, “X days”
assigneeNamestringNoName of assignee

list_tickets

ParameterTypeRequiredDescription
statusstringNoOpen, Resolved, Closed, On Hold, Waiting, or All (default: Open)
limitintegerNoMax results, 1-50 (default: 10)

get_ticket

ParameterTypeRequiredDescription
ticketIdstringYesThe ticket ID to retrieve

search_tickets

ParameterTypeRequiredDescription
querystringYesSearch query for title/description
limitintegerNoMax results, 1-50 (default: 10)

add_ticket_reply

ParameterTypeRequiredDescription
ticketIdstringYesThe ticket ID to reply to
messagestringYesThe reply message
authorNamestringYesName of the person replying
authorEmailstringYesEmail of the person replying

list_tasks

ParameterTypeRequiredDescription
statusstringNoCreated, Assigned, In Progress, Completed, Canceled, or All
limitintegerNoMax results, 1-50 (default: 10)

Security

Authentication

  • All requests require a valid API key in the X-API-Key header or as a Bearer token
  • Two types of keys are supported:
    • User keys (format: hdsk_...): Generated via the Auth Portal, tied to a Google account
    • Legacy keys: Static keys set via Firebase secrets (for backward compatibility)

Key Storage & Security

  • User-generated keys are hashed (SHA-256) before storage - raw keys are never stored
  • Keys are associated with the user’s Firebase UID and email for audit trails
  • Usage statistics (last used, call count) are tracked automatically

Multi-Tenant Isolation

  • Each key is associated with a specific tenant
  • Users can only access data within their tenant
  • Tenant ID can be overridden via X-Tenant-ID header if needed

Audit Trail

  • Tickets created via MCP are marked with submitterId: 'mcp-submission'
  • User-generated keys include the user’s identity in all operations

Troubleshooting

”Invalid or missing API key”

Ensure your API key matches the one set in Firebase secrets:

Terminal window
firebase functions:secrets:access MCP_API_KEY

“Access denied to this ticket”

The ticket belongs to a different tenant. Check the X-Tenant-ID header matches the ticket’s tenant.

Cold Start Delays

The first request after idle may take 2-5 seconds due to Firebase cold start. Subsequent requests are faster.

Claude Code Shows “failed” Status

  1. Check Cloud Run IAM: Ensure “Use IAM to authenticate incoming requests” is disabled in Cloud Run Security settings
  2. Verify the URL: The SSE endpoint is /sse, not the root URL
  3. Restart Claude Code: After changing .mcp.json, restart Claude Code
  4. Test the endpoint manually:
    Terminal window
    curl -H "X-API-Key: your-key" https://mcp-a5kjn6gt4q-uc.a.run.app/sse
    You should see event: endpoint followed by a URL

Claude Code Shows “needs authentication”

This happens when OAuth fields are expected. The helpdesk MCP uses header-based authentication, not OAuth. Make sure your .mcp.json only contains type, url, and headers fields - no OAuth configuration.

Endpoints

EndpointMethodDescription
/GETServer info
/POSTHTTP JSON-RPC transport
/sseGETSSE transport connection
/messagePOSTSSE message endpoint (used by SSE clients)