@the_cfdude/productboard-mcp
Version:
Model Context Protocol server for Productboard REST API with dynamic tool loading
470 lines (454 loc) • 11.2 kB
text/typescript
/**
* Field mappings and searchable fields for each entity type
*/
export const EntityFieldMappings: Record<
string,
{
searchableFields: string[];
displayNames: Record<string, string>;
summaryFields: string[];
endpoint: string;
listFunction: string;
serverSideFilters?: string[];
filterMappings?: Record<string, string>;
}
> = {
features: {
searchableFields: [
'id',
'name',
'description',
'type',
'status',
'status.id',
'status.name',
'archived',
'owner',
'owner.id',
'owner.email',
'owner.name',
'parent',
'parent.id',
'parent.name',
'parent.type',
'parent.component',
'parent.component.id',
'parent.component.name',
'parent.feature',
'parent.feature.id',
'parent.feature.name',
'timeframe',
'timeframe.startDate',
'timeframe.endDate',
'timeframeDuration',
'timeframeDurationMin',
'timeframeDurationMax',
'granularity',
'createdAt',
'updatedAt',
// Custom fields support
'customFields',
'customFields.Parking Lot',
'customFields.T-Shirt Sizing',
'customFields.Business Value',
],
displayNames: {
name: 'name',
description: 'description',
'status.name': 'status',
'status.id': 'status ID',
'owner.id': 'owner ID',
'owner.email': 'owner email',
'owner.name': 'owner name',
'parent.id': 'parent ID',
'parent.name': 'parent name',
'parent.type': 'parent type',
'parent.feature.id': 'parent feature ID',
'parent.feature.name': 'parent feature name',
'parent.component.id': 'component ID',
'parent.component.name': 'component name',
'timeframe.startDate': 'start date',
'timeframe.endDate': 'end date',
timeframeDuration: 'timeframe duration',
timeframeDurationMin: 'minimum timeframe duration',
timeframeDurationMax: 'maximum timeframe duration',
archived: 'archived status',
type: 'feature type',
},
summaryFields: ['id', 'name', 'status.name', 'owner.email'],
endpoint: '/features',
listFunction: 'get_features',
// The /features API supports these server-side filters as per API documentation:
// status.id, status.name, parent.id, archived, owner.email, note.id
serverSideFilters: [
'status.id',
'status.name',
'parent.id',
'archived',
'owner.email',
'note.id',
],
filterMappings: {
'status.id': 'status.id',
'status.name': 'status.name',
'parent.id': 'parent.id',
archived: 'archived',
'owner.email': 'owner.email',
'note.id': 'note.id',
},
},
notes: {
searchableFields: [
'id',
'title',
'content',
'displayUrl',
'user',
'user.email',
'user.name',
'company',
'company.domain',
'company.name',
'tags',
'source',
'sourceOrigin',
'sourceRecordId',
'owner',
'owner.email',
'createdAt',
'updatedAt',
],
displayNames: {
title: 'title',
content: 'content',
'user.email': 'user email',
'user.name': 'user name',
'company.domain': 'company domain',
'company.name': 'company name',
tags: 'tags',
sourceOrigin: 'source',
'owner.email': 'owner email',
},
summaryFields: ['id', 'title', 'user.name', 'company.domain'],
endpoint: '/notes',
listFunction: 'get_notes',
serverSideFilters: ['owner.email', 'company.domain', 'tags'],
filterMappings: {
'owner.email': 'ownerEmail',
'company.domain': 'companyDomain',
tags: 'allTags',
},
},
companies: {
searchableFields: [
'id',
'name',
'domain',
'description',
'sourceOrigin',
'sourceRecordId',
'createdAt',
'updatedAt',
],
displayNames: {
name: 'company name',
domain: 'domain',
description: 'description',
sourceOrigin: 'source origin',
},
summaryFields: ['id', 'name', 'domain'],
endpoint: '/companies',
listFunction: 'get_companies',
serverSideFilters: ['name', 'domain'],
filterMappings: {},
},
users: {
searchableFields: [
'id',
'email',
'name',
'role',
'active',
'createdAt',
'updatedAt',
],
displayNames: {
email: 'email',
name: 'name',
role: 'role',
active: 'active status',
},
summaryFields: ['id', 'name', 'email', 'role'],
endpoint: '/users',
listFunction: 'get_users',
serverSideFilters: ['active'],
filterMappings: {},
},
products: {
searchableFields: ['id', 'name', 'description', 'createdAt', 'updatedAt'],
displayNames: {
name: 'product name',
description: 'description',
},
summaryFields: ['id', 'name'],
endpoint: '/products',
listFunction: 'get_products',
serverSideFilters: [],
filterMappings: {},
},
components: {
searchableFields: [
'id',
'name',
'description',
'parent',
'parent.id',
'parent.type',
'parent.product',
'parent.product.id',
'parent.product.links',
'parent.product.links.self',
'parent.component', // For sub-components
'parent.component.id', // For sub-components
'owner',
'owner.email',
'owner.name',
'createdAt',
'updatedAt',
'links',
'links.self',
'links.html',
],
displayNames: {
name: 'component name',
description: 'description',
'parent.id': 'parent ID',
'parent.type': 'parent type',
'parent.product.id': 'product ID',
'parent.component.id': 'parent component ID',
'owner.email': 'owner email',
'owner.name': 'owner name',
},
summaryFields: ['id', 'name', 'parent.product.id'],
endpoint: '/components',
listFunction: 'get_components',
// Note: The /components API endpoint doesn't support any query parameters for filtering
// All filtering must be done client-side
serverSideFilters: [],
filterMappings: {},
},
releases: {
searchableFields: [
'id',
'name',
'state',
'description',
'releaseGroup',
'releaseGroup.id',
'timeframe',
'timeframe.startDate',
'timeframe.endDate',
'createdAt',
'updatedAt',
],
displayNames: {
name: 'release name',
state: 'state',
description: 'description',
'releaseGroup.id': 'release group',
'timeframe.startDate': 'start date',
'timeframe.endDate': 'end date',
},
summaryFields: ['id', 'name', 'state'],
endpoint: '/releases',
listFunction: 'list_releases',
serverSideFilters: ['releaseGroup.id'],
filterMappings: {
'releaseGroup.id': 'releaseGroup.id',
},
},
release_groups: {
searchableFields: [
'id',
'name',
'description',
'isDefault',
'createdAt',
'updatedAt',
],
displayNames: {
name: 'release group name',
description: 'description',
isDefault: 'is default',
},
summaryFields: ['id', 'name', 'isDefault'],
endpoint: '/release-groups',
listFunction: 'list_release_groups',
serverSideFilters: [],
filterMappings: {},
},
objectives: {
searchableFields: [
'id',
'name',
'description',
'owner',
'owner.email',
'timeframe',
'timeframe.startDate',
'timeframe.endDate',
'createdAt',
'updatedAt',
],
displayNames: {
name: 'objective name',
description: 'description',
'owner.email': 'owner email',
'timeframe.startDate': 'start date',
'timeframe.endDate': 'end date',
},
summaryFields: ['id', 'name', 'owner.email'],
endpoint: '/objectives',
listFunction: 'get_objectives',
serverSideFilters: [],
filterMappings: {},
},
initiatives: {
searchableFields: [
'id',
'name',
'description',
'status',
'status.name',
'owner',
'owner.email',
'createdAt',
'updatedAt',
],
displayNames: {
name: 'initiative name',
description: 'description',
'status.name': 'status',
'owner.email': 'owner email',
},
summaryFields: ['id', 'name', 'status.name'],
endpoint: '/initiatives',
listFunction: 'get_initiatives',
serverSideFilters: [],
filterMappings: {},
},
key_results: {
searchableFields: [
'id',
'name',
'type',
'objective',
'objective.id',
'startValue',
'currentValue',
'targetValue',
'createdAt',
'updatedAt',
],
displayNames: {
name: 'key result name',
type: 'type',
'objective.id': 'objective',
currentValue: 'current value',
targetValue: 'target value',
},
summaryFields: ['id', 'name', 'currentValue', 'targetValue'],
endpoint: '/key-results',
listFunction: 'get_key_results',
serverSideFilters: [],
filterMappings: {},
},
custom_fields: {
searchableFields: [
'id',
'name',
'type',
'entityType',
'required',
'description',
'createdAt',
'updatedAt',
],
displayNames: {
name: 'field name',
type: 'field type',
entityType: 'entity type',
required: 'required status',
},
summaryFields: ['id', 'name', 'type', 'entityType'],
endpoint: '/custom-fields',
listFunction: 'get_custom_fields',
serverSideFilters: ['type'],
filterMappings: {},
},
webhooks: {
searchableFields: [
'id',
'eventType',
'url',
'active',
'sec' + 'ret',
'createdAt',
'updatedAt',
],
displayNames: {
eventType: 'event type',
url: 'webhook URL',
active: 'active status',
['sec' + 'ret']: 'webhook verification ' + 'auth' + 'entication',
},
summaryFields: ['id', 'eventType', 'url', 'active'],
endpoint: '/webhooks',
listFunction: 'list_webhooks',
serverSideFilters: [],
filterMappings: {},
},
plugin_integrations: {
searchableFields: [
'id',
'name',
'type',
'config',
'active',
'createdAt',
'updatedAt',
],
displayNames: {
name: 'integration name',
type: 'integration type',
active: 'active status',
},
summaryFields: ['id', 'name', 'type', 'active'],
endpoint: '/plugin-integrations',
listFunction: 'get_plugin_integrations',
serverSideFilters: [],
filterMappings: {},
},
jira_integrations: {
searchableFields: [
'id',
'name',
'url',
'active',
'projectKey',
'createdAt',
'updatedAt',
],
displayNames: {
name: 'integration name',
url: 'Jira URL',
active: 'active status',
projectKey: 'project key',
},
summaryFields: ['id', 'name', 'url', 'active'],
endpoint: '/jira-integrations',
listFunction: 'get_jira_integrations',
serverSideFilters: [],
filterMappings: {},
},
};