MCP Integration
What Is MCP?
The Model Context Protocol (MCP) is an open protocol that lets AI clients (Claude Desktop, VS Code, and any MCP-compatible tool) connect directly to SyncNow. Once connected, the AI client can query your work systems and manage SyncNow configuration using natural language — without switching context.
MCP is to AI applications what USB is to devices — a universal standard that lets any MCP-compatible client talk to SyncNow.
Supported Clients
- ✅ VS Code (Claude Code and other MCP extensions)
- ✅ Claude Desktop
- ✅ Any MCP-compatible client supporting OAuth 2.0
Endpoints
SyncNow exposes two MCP endpoints with different tool scopes:
| Endpoint | Tools | Use for |
|---|---|---|
POST /mcp | 4 AI query tools | Day-to-day queries against work systems |
POST /mcp/admin | 4 AI tools + 30 management tools (34 total) | Process setup, mapping edits, bulk sync, status investigation |
Connect to /mcp unless you need to manage sync processes or connectors. The lean tool list keeps AI context windows clean and responses fast.
Authentication
SyncNow uses OAuth 2.0 + PKCE to authenticate MCP clients. After the one-time OAuth consent flow, the client receives a token that is used for all subsequent MCP requests.
Two token types are supported depending on your account type:
| Account Type | Token Format | Authorization Header |
|---|---|---|
| Azure AD / External users | JWT | Bearer eyJhbGci... |
| SyncNow internal users | MCP PAT (syncnow_mcp_{guid}) | McpToken syncnow_mcp_oz... |
Both use the same OAuth consent screen. The server issues the correct token type automatically.
OAuth Flow (One-Time Setup)
1. Client generates PKCE challenge
code_verifier = random_string(128)
code_challenge = base64url(sha256(code_verifier))
2. Client opens browser →
GET /oauth/authorize
?client_id=vscode-mcp-test
&redirect_uri=http://127.0.0.1:{port}/
&scope=mcp:read mcp:write
&response_type=code
&code_challenge={challenge}
&code_challenge_method=S256
3. User logs in to SyncNow, approves consent screen
4. Browser redirects back to client with authorization code
5. Client exchanges code for token →
POST /oauth/token
grant_type=authorization_code
&code={code}
&code_verifier={verifier}
&client_id=vscode-mcp-test
&redirect_uri=http://127.0.0.1:{port}/
6. Server returns access token (JWT or MCP PAT)
7. Client stores token — used for all MCP requests
MCP clients (VS Code, Claude Desktop) handle this flow automatically. You just log in once in the browser popup.
Client Setup
VS Code
Create .vscode/mcp-servers.json in your project (or user settings):
{
"syncnow": {
"url": "http://localhost:5030/mcp",
"oauth": {
"authorizationUrl": "http://localhost:5030/oauth/authorize",
"tokenUrl": "http://localhost:5030/oauth/token",
"clientId": "vscode-mcp-test",
"scope": "mcp:read mcp:write"
}
},
"syncnow-admin": {
"url": "http://localhost:5030/mcp/admin",
"oauth": {
"authorizationUrl": "http://localhost:5030/oauth/authorize",
"tokenUrl": "http://localhost:5030/oauth/token",
"clientId": "vscode-mcp-test",
"scope": "mcp:read mcp:write"
}
}
}
Add
syncnow-adminonly if you need process or connector management tools.
First use: Trigger an MCP tool (e.g., ask Claude Code about your work items). A browser window opens for OAuth login. After approving, the token is stored in VS Code's keychain and MCP tools are available immediately.
Claude Desktop
Edit ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or the equivalent on Windows:
{
"mcpServers": {
"syncnow": {
"command": "mcp-client",
"args": [
"--url", "http://localhost:5030/mcp",
"--oauth-authorize", "http://localhost:5030/oauth/authorize",
"--oauth-token", "http://localhost:5030/oauth/token",
"--client-id", "vscode-mcp-test"
]
}
}
}
Restart Claude Desktop after editing. The OAuth login prompt appears on first use.
Typical session:
User: "Show me my open Jira tickets"
Claude: [calls GetAvailableAgents] → finds "jira-agent"
Claude: [calls Query("jira-agent", "show me my open Jira tickets")]
Claude: "Here are your 5 open tickets: ..."
MCP Tools Reference
AI Query Tools — available at /mcp and /mcp/admin
These four tools cover all day-to-day AI interactions with your work systems.
GetAvailableAgents
Returns all active AI agents configured in this SyncNow instance. Always call this first before Query or SearchKnowledge to discover valid agentSystemName values.
Arguments: none
Response:
[
{ "systemName": "jira-agent", "displayName": "Jira", "systemTypeKey": "jira" },
{ "systemName": "servicenow-agent", "displayName": "ServiceNow", "systemTypeKey": "servicenow" }
]
Query
Main entry point. Runs a natural language question through the full AI pipeline. Intent is auto-detected:
- Action intent → queries live work items from your work system
- Knowledge intent → searches SyncNow internal documentation
Arguments:
| Parameter | Required | Description |
|---|---|---|
agentSystemName | ✅ | Agent systemName from GetAvailableAgents |
question | ✅ | Your question or request |
context | ❌ | Optional Base64-encoded context (code snippet, document excerpt) |
Example:
{
"name": "Query",
"arguments": {
"agentSystemName": "jira-agent",
"question": "Show me open P1 bugs assigned to me"
}
}
Response includes: structured blocks (Markdown, Code, Diagram, Table, PDF/Excel downloads), HTML, raw text, intent type, and AI flow steps.
SearchKnowledge
Forces the Knowledge path — searches SyncNow internal documentation, how-to guides, and configuration docs. Use this when you need reference information rather than live work item data.
Arguments: same as Query (agentSystemName + question)
GetResponseSchema
Returns schema documentation for the AI response format — content block types, rendering guidelines, and property descriptions. Useful for clients that need to understand the response structure programmatically.
Arguments: none
Management Tools — /mcp/admin only
The admin endpoint adds 30 tools across 6 groups for managing SyncNow programmatically.
Sync Process Tools
| Tool | Description |
|---|---|
SearchProcesses | List sync processes by name or active state |
GetProcess | Get full details of a process by ID |
CreateProcess | Create a new sync process linking two systems |
UpdateProcess | Update name, description, or active state |
DeleteProcess | Soft-delete a process (restorable via UI) |
Mapping Tools
| Tool | Description |
|---|---|
GetMappingJsonSchema | Get the full schema for MappingJSON — call before editing any mapping |
SearchMappings | List mapping definitions |
GetMapping | Get a mapping definition by ID including full MappingJSON |
GetMappingForProcess | Get a process's mapping directly by process ID |
UpdateMappingMetadata | Rename a mapping definition |
UpdateMappingDefinition | Replace the full MappingJSON (entity pairs, field rules, transforms) |
Bulk Sync Tools
| Tool | Description |
|---|---|
TriggerBulkSync | Queue a full re-synchronization for a process |
GetBulkSyncStatus | Poll bulk sync progress — returns status, percent, entity counts |
Adapter / Connector Tools
| Tool | Description |
|---|---|
GetSystemTypes | List all licensed connector types (call first when creating a connector) |
SearchAdapters | List configured connector instances |
GetAdapter | Get a connector's configuration by ID (credentials masked) |
CreateAdapter | Create a new connector instance |
UpdateAdapter | Update an existing connector |
DeleteAdapter | Delete a connector (fails if referenced by active processes) |
ValidateAdapter | Test connectivity for a connector |
ListAdapterProjects | Discover sub-projects / boards available in a connector |
Sync Template Tools
| Tool | Description |
|---|---|
SearchTemplates | Browse the sync template gallery |
GetTemplateDetails | Get a template's full MappingJSON and available versions |
ApplyTemplateToProcess | Apply a template to a process, replacing its mapping |
Sync Status Tools
| Tool | Description |
|---|---|
SearchSyncRuns | Search run history by process, date range, and status |
GetSyncRun | Get full metadata for a single run |
GetSyncRunLog | Read a paginated slice of the run's CSV log |
GetActiveSyncRuns | Get all currently in-progress runs for a process |
SearchSyncRunEntities | Search entity-level results within a run |
GetEntitySyncHistory | Get the full sync history for a specific entity across all runs |
Common Workflows
Query a Work System
1. GetAvailableAgents()
→ discovers: [{ systemName: "jira-agent" }, ...]
2. Query("jira-agent", "show me open P1 bugs assigned to me")
→ queries Jira, returns structured results
Set Up a New Connector and Process
1. GetSystemTypes() → find the type key for Jira, ServiceNow, etc.
2. CreateAdapter(...) → create the connector
3. ValidateAdapter(id) → confirm connectivity
4. ListAdapterProjects(id) → discover sub-project IDs
5. CreateProcess(...) → create the sync process
Apply a Template
1. SearchTemplates(name: "Jira")
2. GetTemplateDetails(uniqueShortName)
3. ApplyTemplateToProcess(uniqueShortName, processId)
4. TriggerBulkSync(processId) → re-sync with the new mapping
Investigate a Sync Failure
1. SearchSyncRuns(processId, from, to, status: "Fail")
2. GetSyncRunLog(syncRunId)
3. SearchSyncRunEntities(syncRunId, onlyErrors: true)
4. GetEntitySyncHistory(systemId, entityId) → for persistent failures
Protocol Details
SyncNow implements the standard MCP JSON-RPC 2.0 protocol.
Supported methods: initialize, tools/list, tools/call, prompts/list, resources/list
Initialize request:
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"clientInfo": { "name": "my-client", "version": "1.0.0" }
}
}
Tool call request:
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "Query",
"arguments": {
"agentSystemName": "jira-agent",
"question": "Show me my open P1 bugs"
}
}
}
The MCP server is stateless — it holds no conversation history between calls. The MCP client (VS Code, Claude Desktop) manages conversation context and passes it with each request.
Troubleshooting
401 Unauthorized
- Re-run the OAuth flow to get a fresh token
- Verify token format:
syncnow_mcp_{32-hex-chars}for internal users, JWT for Azure AD users
"agentSystemName cannot be empty"
Always call GetAvailableAgents() first — do not hardcode agent names.
"No agent found with the specified system name"
The agentSystemName doesn't match any active agent. Call GetAvailableAgents() and use the exact systemName from the response.
400 Bad Request
Ensure your request is valid JSON-RPC 2.0:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": { "name": "GetAvailableAgents", "arguments": {} }
}
OAuth Errors
| Error | Cause | Fix |
|---|---|---|
invalid_client | Client ID not found | Check clientId matches server config |
invalid_redirect_uri | Redirect URI not in allowlist | Contact your SyncNow administrator |
invalid_grant (PKCE failed) | Code verifier mismatch | Client-side issue — retry OAuth flow |
invalid_grant (expired) | More than 10 min between authorize and token | Complete OAuth flow faster |
Resources
- MCP Specification
- Security & Permissions — AI Query permission setup