@fruition/fcp-mcp-server 1.19.0 → 1.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +137 -0
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -99,6 +99,7 @@ const TOOL_PERMISSIONS = {
99
99
  fcp_create_launch: 'admin',
100
100
  fcp_update_launch: 'admin',
101
101
  fcp_update_site: 'admin',
102
+ fcp_update_client_profile: 'admin',
102
103
  fcp_delete_checklist_item: 'admin',
103
104
  fcp_shield_add_domain: 'admin',
104
105
  fcp_shield_update_domain: 'admin',
@@ -142,6 +143,8 @@ const TOOL_PERMISSIONS = {
142
143
  fcp_list_sites: 'viewer',
143
144
  fcp_search_sites: 'viewer',
144
145
  fcp_get_site: 'viewer',
146
+ fcp_list_clients: 'viewer',
147
+ fcp_get_client: 'viewer',
145
148
  fcp_get_local_setup_guide: 'viewer',
146
149
  fcp_shield_list_domains: 'viewer',
147
150
  fcp_shield_get_domain: 'viewer',
@@ -514,6 +517,35 @@ class FCPClient {
514
517
  async getLocalSetupGuide(siteId) {
515
518
  return this.fetch(`/api/sites/${siteId}/local-setup`);
516
519
  }
520
+ // WebOps Client Directory
521
+ async listClients(filters) {
522
+ const params = new URLSearchParams();
523
+ if (filters?.q)
524
+ params.set('q', filters.q);
525
+ if (filters?.webops_lead)
526
+ params.set('webops_lead', filters.webops_lead);
527
+ if (filters?.contract_type)
528
+ params.set('contract_type', filters.contract_type);
529
+ if (filters?.tier)
530
+ params.set('tier', filters.tier);
531
+ if (filters?.marketing !== undefined)
532
+ params.set('marketing', String(filters.marketing));
533
+ if (filters?.status)
534
+ params.set('status', filters.status);
535
+ if (filters?.limit)
536
+ params.set('limit', String(filters.limit));
537
+ const qs = params.toString();
538
+ return this.fetch(`/api/clients${qs ? `?${qs}` : ''}`);
539
+ }
540
+ async getClient(accountId) {
541
+ return this.fetch(`/api/clients/${accountId}/profile`);
542
+ }
543
+ async updateClientProfile(accountId, updates) {
544
+ return this.fetch(`/api/clients/${accountId}/profile`, {
545
+ method: 'PUT',
546
+ body: JSON.stringify(updates),
547
+ });
548
+ }
517
549
  // Shield Domain Management
518
550
  async shieldListDomains(filters) {
519
551
  const params = new URLSearchParams();
@@ -2455,6 +2487,89 @@ const TOOLS = [
2455
2487
  required: ['website_id'],
2456
2488
  },
2457
2489
  },
2490
+ // WebOps Client Directory
2491
+ {
2492
+ name: 'fcp_list_clients',
2493
+ description: 'List client accounts from the WebOps Client Directory with their WebOps profile (lead, sponsor, contract type, service tier, site count). Use to answer "who manages X", "list all retainer clients", "which clients does Janine lead".',
2494
+ inputSchema: {
2495
+ type: 'object',
2496
+ properties: {
2497
+ q: { type: 'string', description: 'Search by client/account name (substring match)' },
2498
+ webops_lead: { type: 'string', description: 'Filter by WebOps lead (e.g. "Janine", "Mike")' },
2499
+ contract_type: {
2500
+ type: 'string',
2501
+ description: 'Filter by contract type: tm, block, tm_or_block, retainer, pro_bono, other',
2502
+ },
2503
+ tier: {
2504
+ type: 'string',
2505
+ description: 'Filter by account service tier: standard, frucare, ada, redteam',
2506
+ },
2507
+ marketing: {
2508
+ type: 'boolean',
2509
+ description: 'Filter to marketing clients only (true) or non-marketing (false)',
2510
+ },
2511
+ status: {
2512
+ type: 'string',
2513
+ description: 'Profile status: active (default), deactivated, or all',
2514
+ },
2515
+ limit: { type: 'number', description: 'Max rows to return (default 300)' },
2516
+ },
2517
+ },
2518
+ },
2519
+ {
2520
+ name: 'fcp_get_client',
2521
+ description: "Get the full WebOps profile for one client account: relationship/commercial data, primary contacts, and all of the account's websites with detected analytics (GA4/GTM/Clarity/Bugherd).",
2522
+ inputSchema: {
2523
+ type: 'object',
2524
+ properties: {
2525
+ account_id: { type: 'number', description: 'The account ID (required)' },
2526
+ },
2527
+ required: ['account_id'],
2528
+ },
2529
+ },
2530
+ {
2531
+ name: 'fcp_update_client_profile',
2532
+ description: "Update business/relationship fields on a client's WebOps profile. Technical facts (CMS, hosting, FruCare) are NOT editable here -- FCP detects/owns those. Only provided fields change.",
2533
+ inputSchema: {
2534
+ type: 'object',
2535
+ properties: {
2536
+ account_id: { type: 'number', description: 'The account ID to update (required)' },
2537
+ webops_lead: { type: 'string', description: 'Canonical WebOps lead' },
2538
+ relationship_sponsor: { type: 'string', description: 'Relationship sponsor' },
2539
+ contract_type: {
2540
+ type: 'string',
2541
+ description: 'tm, block, tm_or_block, retainer, pro_bono, none, other',
2542
+ },
2543
+ contract_rate: { type: 'string', description: 'Freeform rate (e.g. "$155/hour")' },
2544
+ contract_notes: { type: 'string', description: 'Contract notes' },
2545
+ is_marketing_client: { type: 'boolean', description: 'Whether this is a marketing client' },
2546
+ comms_platform: {
2547
+ type: 'string',
2548
+ description: 'Client collaboration platform (Google / MS Teams)',
2549
+ },
2550
+ client_time_zone: { type: 'string', description: 'Client time zone' },
2551
+ meeting_cadence: { type: 'string', description: 'Meeting cadence' },
2552
+ meeting_attendees: { type: 'string', description: 'Meeting attendees' },
2553
+ last_client_contact: { type: 'string', description: 'Last contact note' },
2554
+ looker_studio_url: { type: 'string', description: 'Looker Studio report URL' },
2555
+ shared_drive_url: { type: 'string', description: 'Shared drive URL' },
2556
+ client_assets_url: { type: 'string', description: 'Client assets URL' },
2557
+ unroo_board_url: { type: 'string', description: 'Unroo board URL' },
2558
+ client_goals: { type: 'string', description: 'Client goals & focus areas' },
2559
+ what_you_need_to_know: {
2560
+ type: 'string',
2561
+ description: 'Key things to know about this client',
2562
+ },
2563
+ general_notes: { type: 'string', description: 'General notes' },
2564
+ status: { type: 'string', description: 'active or deactivated' },
2565
+ mark_reviewed: {
2566
+ type: 'boolean',
2567
+ description: 'Set true to stamp last_reviewed_at = now (confirms the profile is accurate)',
2568
+ },
2569
+ },
2570
+ required: ['account_id'],
2571
+ },
2572
+ },
2458
2573
  // Fruition Shield - Shared WAF Gateway
2459
2574
  {
2460
2575
  name: 'fcp_shield_list_domains',
@@ -3253,6 +3368,28 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
3253
3368
  ],
3254
3369
  };
3255
3370
  }
3371
+ // WebOps Client Directory Handlers
3372
+ case 'fcp_list_clients': {
3373
+ const filters = args;
3374
+ const result = await client.listClients(filters);
3375
+ return {
3376
+ content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
3377
+ };
3378
+ }
3379
+ case 'fcp_get_client': {
3380
+ const { account_id } = args;
3381
+ const result = await client.getClient(account_id);
3382
+ return {
3383
+ content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
3384
+ };
3385
+ }
3386
+ case 'fcp_update_client_profile': {
3387
+ const { account_id, ...updates } = args;
3388
+ const result = await client.updateClientProfile(account_id, updates);
3389
+ return {
3390
+ content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
3391
+ };
3392
+ }
3256
3393
  // Launch CRUD Handlers
3257
3394
  case 'fcp_create_launch': {
3258
3395
  const { name, platform, launch_type, target_launch_date, ...rest } = args;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fruition/fcp-mcp-server",
3
- "version": "1.19.0",
3
+ "version": "1.20.0",
4
4
  "description": "MCP Server for FCP Launch Coordination System - enables Claude Code to interact with FCP launches and track development time",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",