@mentionova/mcp-server 1.2.0 → 1.3.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/index.js +505 -0
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -473,6 +473,511 @@ server.tool(
473
473
  }
474
474
  );
475
475
 
476
+ // --- Workflows ---
477
+
478
+ server.tool(
479
+ "mentionova_list_workflows",
480
+ "List automation workflows in a workspace",
481
+ {
482
+ workspace_id: z.string().describe("Workspace UUID"),
483
+ status: z.enum(["draft", "active", "paused", "archived"]).optional().describe("Filter by status"),
484
+ limit: z.number().optional(),
485
+ offset: z.number().optional(),
486
+ },
487
+ async ({ workspace_id, status, limit, offset }) => {
488
+ const data = await api(`/workspaces/${workspace_id}/workflows`, { status, limit, offset });
489
+ return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
490
+ }
491
+ );
492
+
493
+ server.tool(
494
+ "mentionova_create_workflow",
495
+ "Create a new automation workflow",
496
+ {
497
+ workspace_id: z.string().describe("Workspace UUID"),
498
+ name: z.string().describe("Workflow name"),
499
+ description: z.string().optional(),
500
+ status: z.enum(["draft", "active", "paused"]).optional(),
501
+ graph: z.object({ steps: z.array(z.any()), edges: z.array(z.any()) }).optional().describe("DAG definition"),
502
+ schedule_cron: z.string().optional().describe("Cron expression for scheduled runs"),
503
+ },
504
+ async ({ workspace_id, ...body }) => {
505
+ const data = await apiPost(`/workspaces/${workspace_id}/workflows`, body);
506
+ return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
507
+ }
508
+ );
509
+
510
+ server.tool(
511
+ "mentionova_get_workflow",
512
+ "Get a specific workflow by ID",
513
+ {
514
+ workspace_id: z.string().describe("Workspace UUID"),
515
+ workflow_id: z.string().describe("Workflow UUID"),
516
+ },
517
+ async ({ workspace_id, workflow_id }) => {
518
+ const data = await api(`/workspaces/${workspace_id}/workflows/${workflow_id}`);
519
+ return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
520
+ }
521
+ );
522
+
523
+ server.tool(
524
+ "mentionova_update_workflow",
525
+ "Update a workflow's name, status, graph, or schedule",
526
+ {
527
+ workspace_id: z.string().describe("Workspace UUID"),
528
+ workflow_id: z.string().describe("Workflow UUID"),
529
+ name: z.string().optional(),
530
+ description: z.string().optional(),
531
+ status: z.enum(["draft", "active", "paused", "archived"]).optional(),
532
+ graph: z.object({ steps: z.array(z.any()), edges: z.array(z.any()) }).optional(),
533
+ schedule_cron: z.string().optional(),
534
+ },
535
+ async ({ workspace_id, workflow_id, ...body }) => {
536
+ const data = await apiPatch(`/workspaces/${workspace_id}/workflows/${workflow_id}`, body);
537
+ return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
538
+ }
539
+ );
540
+
541
+ server.tool(
542
+ "mentionova_delete_workflow",
543
+ "Delete a workflow",
544
+ {
545
+ workspace_id: z.string().describe("Workspace UUID"),
546
+ workflow_id: z.string().describe("Workflow UUID"),
547
+ },
548
+ async ({ workspace_id, workflow_id }) => {
549
+ const data = await apiDelete(`/workspaces/${workspace_id}/workflows/${workflow_id}`);
550
+ return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
551
+ }
552
+ );
553
+
554
+ server.tool(
555
+ "mentionova_list_workflow_runs",
556
+ "List runs for a specific workflow",
557
+ {
558
+ workspace_id: z.string().describe("Workspace UUID"),
559
+ workflow_id: z.string().describe("Workflow UUID"),
560
+ status: z.enum(["pending", "running", "completed", "partial", "failed", "cancelled"]).optional(),
561
+ limit: z.number().optional(),
562
+ offset: z.number().optional(),
563
+ },
564
+ async ({ workspace_id, workflow_id, status, limit, offset }) => {
565
+ const data = await api(`/workspaces/${workspace_id}/workflows/${workflow_id}/runs`, { status, limit, offset });
566
+ return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
567
+ }
568
+ );
569
+
570
+ server.tool(
571
+ "mentionova_trigger_workflow",
572
+ "Trigger a workflow run via the API",
573
+ {
574
+ workspace_id: z.string().describe("Workspace UUID"),
575
+ workflow_id: z.string().describe("Workflow UUID"),
576
+ input: z.record(z.any()).optional().describe("Input payload for the run"),
577
+ },
578
+ async ({ workspace_id, workflow_id, input }) => {
579
+ const data = await apiPost(`/workspaces/${workspace_id}/workflows/${workflow_id}/runs`, { input });
580
+ return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
581
+ }
582
+ );
583
+
584
+ // --- Reddit Engagement ---
585
+
586
+ server.tool(
587
+ "mentionova_list_reddit_comments",
588
+ "List Reddit comment drafts (engagement queue) for a workspace",
589
+ {
590
+ workspace_id: z.string().describe("Workspace UUID"),
591
+ status: z.enum(["draft", "approved", "posted", "skipped"]).optional(),
592
+ subreddit: z.string().optional().describe("Filter by subreddit"),
593
+ limit: z.number().optional(),
594
+ offset: z.number().optional(),
595
+ },
596
+ async ({ workspace_id, status, subreddit, limit, offset }) => {
597
+ const data = await api(`/workspaces/${workspace_id}/reddit`, { status, subreddit, limit, offset });
598
+ return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
599
+ }
600
+ );
601
+
602
+ server.tool(
603
+ "mentionova_update_reddit_comment",
604
+ "Update a Reddit comment draft (edit text, change status, assign)",
605
+ {
606
+ workspace_id: z.string().describe("Workspace UUID"),
607
+ comment_id: z.string().describe("Comment UUID"),
608
+ status: z.enum(["draft", "approved", "posted", "skipped"]).optional(),
609
+ edited_comment: z.string().optional().describe("Edited comment text"),
610
+ assigned_to: z.string().optional().describe("User UUID to assign to"),
611
+ },
612
+ async ({ workspace_id, comment_id, ...body }) => {
613
+ const data = await apiPatch(`/workspaces/${workspace_id}/reddit`, { comment_id, ...body });
614
+ return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
615
+ }
616
+ );
617
+
618
+ server.tool(
619
+ "mentionova_delete_reddit_comment",
620
+ "Delete a Reddit comment draft",
621
+ {
622
+ workspace_id: z.string().describe("Workspace UUID"),
623
+ comment_id: z.string().describe("Comment UUID"),
624
+ },
625
+ async ({ workspace_id, comment_id }) => {
626
+ const data = await apiDelete(`/workspaces/${workspace_id}/reddit?comment_id=${comment_id}`);
627
+ return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
628
+ }
629
+ );
630
+
631
+ // --- Reports ---
632
+
633
+ server.tool(
634
+ "mentionova_list_shared_reports",
635
+ "List shared report links for a workspace",
636
+ {
637
+ workspace_id: z.string().describe("Workspace UUID"),
638
+ include_revoked: z.enum(["true", "false"]).optional(),
639
+ limit: z.number().optional(),
640
+ offset: z.number().optional(),
641
+ },
642
+ async ({ workspace_id, include_revoked, limit, offset }) => {
643
+ const data = await api(`/workspaces/${workspace_id}/reports`, { include_revoked, limit, offset });
644
+ return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
645
+ }
646
+ );
647
+
648
+ server.tool(
649
+ "mentionova_create_shared_report",
650
+ "Create a shareable report link for a workspace",
651
+ {
652
+ workspace_id: z.string().describe("Workspace UUID"),
653
+ channel: z.string().optional().describe("Filter report to a specific AI engine channel"),
654
+ expires_at: z.string().optional().describe("Expiration date (ISO 8601)"),
655
+ },
656
+ async ({ workspace_id, channel, expires_at }) => {
657
+ const data = await apiPost(`/workspaces/${workspace_id}/reports`, { channel, expires_at });
658
+ return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
659
+ }
660
+ );
661
+
662
+ server.tool(
663
+ "mentionova_revoke_shared_report",
664
+ "Revoke a shared report link",
665
+ {
666
+ workspace_id: z.string().describe("Workspace UUID"),
667
+ report_id: z.string().describe("Shared report UUID"),
668
+ },
669
+ async ({ workspace_id, report_id }) => {
670
+ const data = await apiDelete(`/workspaces/${workspace_id}/reports?report_id=${report_id}`);
671
+ return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
672
+ }
673
+ );
674
+
675
+ server.tool(
676
+ "mentionova_list_geo_reports",
677
+ "List GEO (weekly AI visibility) reports for a workspace",
678
+ {
679
+ workspace_id: z.string().describe("Workspace UUID"),
680
+ status: z.enum(["pending", "generating", "ready", "failed"]).optional(),
681
+ limit: z.number().optional(),
682
+ offset: z.number().optional(),
683
+ },
684
+ async ({ workspace_id, status, limit, offset }) => {
685
+ const data = await api(`/workspaces/${workspace_id}/reports/geo`, { status, limit, offset });
686
+ return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
687
+ }
688
+ );
689
+
690
+ server.tool(
691
+ "mentionova_get_geo_report",
692
+ "Get a GEO report with its content plays",
693
+ {
694
+ workspace_id: z.string().describe("Workspace UUID"),
695
+ report_id: z.string().describe("GEO report UUID"),
696
+ },
697
+ async ({ workspace_id, report_id }) => {
698
+ const data = await api(`/workspaces/${workspace_id}/reports/geo/${report_id}`);
699
+ return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
700
+ }
701
+ );
702
+
703
+ // --- Grid Columns ---
704
+
705
+ server.tool(
706
+ "mentionova_list_grid_columns",
707
+ "List columns in a content grid",
708
+ {
709
+ workspace_id: z.string().describe("Workspace UUID"),
710
+ grid_id: z.string().describe("Grid UUID"),
711
+ },
712
+ async ({ workspace_id, grid_id }) => {
713
+ const data = await api(`/workspaces/${workspace_id}/grids/${grid_id}/columns`);
714
+ return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
715
+ }
716
+ );
717
+
718
+ server.tool(
719
+ "mentionova_create_grid_column",
720
+ "Add a column to a content grid",
721
+ {
722
+ workspace_id: z.string().describe("Workspace UUID"),
723
+ grid_id: z.string().describe("Grid UUID"),
724
+ key: z.string().describe("Column key (unique within grid)"),
725
+ display_name: z.string().describe("Column display name"),
726
+ column_type: z.string().describe("Column type (e.g. text, url, ai_generate)"),
727
+ config: z.record(z.any()).optional().describe("Column configuration"),
728
+ position: z.number().optional().describe("Position (auto-assigned if omitted)"),
729
+ depends_on: z.array(z.string()).optional().describe("Keys of columns this depends on"),
730
+ is_output: z.boolean().optional(),
731
+ },
732
+ async ({ workspace_id, grid_id, ...body }) => {
733
+ const data = await apiPost(`/workspaces/${workspace_id}/grids/${grid_id}/columns`, body);
734
+ return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
735
+ }
736
+ );
737
+
738
+ server.tool(
739
+ "mentionova_update_grid_column",
740
+ "Update a grid column's name, type, config, or position",
741
+ {
742
+ workspace_id: z.string().describe("Workspace UUID"),
743
+ grid_id: z.string().describe("Grid UUID"),
744
+ column_id: z.string().describe("Column UUID"),
745
+ display_name: z.string().optional(),
746
+ column_type: z.string().optional(),
747
+ config: z.record(z.any()).optional(),
748
+ depends_on: z.array(z.string()).optional(),
749
+ is_output: z.boolean().optional(),
750
+ position: z.number().optional(),
751
+ },
752
+ async ({ workspace_id, grid_id, column_id, ...body }) => {
753
+ const data = await apiPatch(`/workspaces/${workspace_id}/grids/${grid_id}/columns/${column_id}`, body);
754
+ return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
755
+ }
756
+ );
757
+
758
+ server.tool(
759
+ "mentionova_delete_grid_column",
760
+ "Delete a grid column and its cells",
761
+ {
762
+ workspace_id: z.string().describe("Workspace UUID"),
763
+ grid_id: z.string().describe("Grid UUID"),
764
+ column_id: z.string().describe("Column UUID"),
765
+ },
766
+ async ({ workspace_id, grid_id, column_id }) => {
767
+ const data = await apiDelete(`/workspaces/${workspace_id}/grids/${grid_id}/columns/${column_id}`);
768
+ return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
769
+ }
770
+ );
771
+
772
+ // --- Grid Rows ---
773
+
774
+ server.tool(
775
+ "mentionova_list_grid_rows",
776
+ "List rows in a content grid",
777
+ {
778
+ workspace_id: z.string().describe("Workspace UUID"),
779
+ grid_id: z.string().describe("Grid UUID"),
780
+ limit: z.number().optional(),
781
+ offset: z.number().optional(),
782
+ },
783
+ async ({ workspace_id, grid_id, limit, offset }) => {
784
+ const data = await api(`/workspaces/${workspace_id}/grids/${grid_id}/rows`, { limit, offset });
785
+ return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
786
+ }
787
+ );
788
+
789
+ server.tool(
790
+ "mentionova_create_grid_row",
791
+ "Add a row to a content grid",
792
+ {
793
+ workspace_id: z.string().describe("Workspace UUID"),
794
+ grid_id: z.string().describe("Grid UUID"),
795
+ source: z.enum(["manual", "csv", "webhook"]).optional().describe("Row source (default: manual)"),
796
+ source_ref: z.record(z.any()).optional(),
797
+ position: z.number().optional(),
798
+ },
799
+ async ({ workspace_id, grid_id, ...body }) => {
800
+ const data = await apiPost(`/workspaces/${workspace_id}/grids/${grid_id}/rows`, body);
801
+ return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
802
+ }
803
+ );
804
+
805
+ server.tool(
806
+ "mentionova_get_grid_row",
807
+ "Get a grid row with all its cell values",
808
+ {
809
+ workspace_id: z.string().describe("Workspace UUID"),
810
+ grid_id: z.string().describe("Grid UUID"),
811
+ row_id: z.string().describe("Row UUID"),
812
+ },
813
+ async ({ workspace_id, grid_id, row_id }) => {
814
+ const data = await api(`/workspaces/${workspace_id}/grids/${grid_id}/rows/${row_id}`);
815
+ return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
816
+ }
817
+ );
818
+
819
+ server.tool(
820
+ "mentionova_update_grid_row",
821
+ "Update a grid row's position or source reference",
822
+ {
823
+ workspace_id: z.string().describe("Workspace UUID"),
824
+ grid_id: z.string().describe("Grid UUID"),
825
+ row_id: z.string().describe("Row UUID"),
826
+ position: z.number().optional(),
827
+ source_ref: z.record(z.any()).optional(),
828
+ },
829
+ async ({ workspace_id, grid_id, row_id, ...body }) => {
830
+ const data = await apiPatch(`/workspaces/${workspace_id}/grids/${grid_id}/rows/${row_id}`, body);
831
+ return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
832
+ }
833
+ );
834
+
835
+ server.tool(
836
+ "mentionova_delete_grid_row",
837
+ "Delete a grid row and its cells",
838
+ {
839
+ workspace_id: z.string().describe("Workspace UUID"),
840
+ grid_id: z.string().describe("Grid UUID"),
841
+ row_id: z.string().describe("Row UUID"),
842
+ },
843
+ async ({ workspace_id, grid_id, row_id }) => {
844
+ const data = await apiDelete(`/workspaces/${workspace_id}/grids/${grid_id}/rows/${row_id}`);
845
+ return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
846
+ }
847
+ );
848
+
849
+ // --- Grid Cells ---
850
+
851
+ server.tool(
852
+ "mentionova_list_grid_cells",
853
+ "List all cells in a content grid",
854
+ {
855
+ workspace_id: z.string().describe("Workspace UUID"),
856
+ grid_id: z.string().describe("Grid UUID"),
857
+ limit: z.number().optional(),
858
+ offset: z.number().optional(),
859
+ },
860
+ async ({ workspace_id, grid_id, limit, offset }) => {
861
+ const data = await api(`/workspaces/${workspace_id}/grids/${grid_id}/cells`, { limit, offset });
862
+ return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
863
+ }
864
+ );
865
+
866
+ server.tool(
867
+ "mentionova_update_grid_cell",
868
+ "Update (or create) a cell value in a grid",
869
+ {
870
+ workspace_id: z.string().describe("Workspace UUID"),
871
+ grid_id: z.string().describe("Grid UUID"),
872
+ row_id: z.string().describe("Row UUID"),
873
+ column_id: z.string().describe("Column UUID"),
874
+ value_text: z.string().optional(),
875
+ value_json: z.record(z.any()).optional(),
876
+ value_number: z.number().optional(),
877
+ },
878
+ async ({ workspace_id, grid_id, ...body }) => {
879
+ const data = await apiPatch(`/workspaces/${workspace_id}/grids/${grid_id}/cells`, body);
880
+ return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
881
+ }
882
+ );
883
+
884
+ // --- Marketplace ---
885
+
886
+ server.tool(
887
+ "mentionova_list_marketplace_profiles",
888
+ "Browse marketplace profiles for collaboration opportunities",
889
+ {
890
+ status: z.enum(["live", "hidden"]).optional(),
891
+ industry: z.string().optional(),
892
+ limit: z.number().optional(),
893
+ offset: z.number().optional(),
894
+ },
895
+ async ({ status, industry, limit, offset }) => {
896
+ const data = await api("/marketplace/profiles", { status, industry, limit, offset });
897
+ return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
898
+ }
899
+ );
900
+
901
+ server.tool(
902
+ "mentionova_get_marketplace_profile",
903
+ "Get a specific marketplace profile",
904
+ {
905
+ profile_id: z.string().describe("Profile UUID"),
906
+ },
907
+ async ({ profile_id }) => {
908
+ const data = await api(`/marketplace/profiles/${profile_id}`);
909
+ return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
910
+ }
911
+ );
912
+
913
+ server.tool(
914
+ "mentionova_create_marketplace_profile",
915
+ "Create a marketplace profile for one of your workspaces",
916
+ {
917
+ workspace_id: z.string().describe("Workspace UUID to create profile for"),
918
+ display_name: z.string().describe("Display name"),
919
+ tagline: z.string().optional(),
920
+ description: z.string().optional(),
921
+ industry: z.string().optional(),
922
+ website_url: z.string().optional(),
923
+ collab_types: z.array(z.enum(["newsletter_swap", "social_cross_post", "co_content", "bundle", "event"])).optional(),
924
+ looking_for: z.string().optional(),
925
+ show_stats: z.boolean().optional(),
926
+ },
927
+ async (body) => {
928
+ const data = await apiPost("/marketplace/profiles", body);
929
+ return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
930
+ }
931
+ );
932
+
933
+ server.tool(
934
+ "mentionova_update_marketplace_profile",
935
+ "Update your marketplace profile",
936
+ {
937
+ profile_id: z.string().describe("Profile UUID"),
938
+ display_name: z.string().optional(),
939
+ tagline: z.string().optional(),
940
+ description: z.string().optional(),
941
+ industry: z.string().optional(),
942
+ website_url: z.string().optional(),
943
+ collab_types: z.array(z.enum(["newsletter_swap", "social_cross_post", "co_content", "bundle", "event"])).optional(),
944
+ looking_for: z.string().optional(),
945
+ show_stats: z.boolean().optional(),
946
+ status: z.enum(["live", "hidden"]).optional(),
947
+ },
948
+ async ({ profile_id, ...body }) => {
949
+ const data = await apiPatch(`/marketplace/profiles/${profile_id}`, body);
950
+ return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
951
+ }
952
+ );
953
+
954
+ server.tool(
955
+ "mentionova_express_interest",
956
+ "Express interest in collaborating with a marketplace profile",
957
+ {
958
+ to_profile: z.string().describe("Target profile UUID"),
959
+ type: z.enum(["interest", "reachout", "pass"]).describe("Type of interest"),
960
+ message: z.string().optional().describe("Message to include"),
961
+ },
962
+ async (body) => {
963
+ const data = await apiPost("/marketplace/interests", body);
964
+ return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
965
+ }
966
+ );
967
+
968
+ server.tool(
969
+ "mentionova_list_marketplace_matches",
970
+ "List your marketplace matches (mutual interests / accepted reachouts)",
971
+ {
972
+ limit: z.number().optional(),
973
+ offset: z.number().optional(),
974
+ },
975
+ async ({ limit, offset }) => {
976
+ const data = await api("/marketplace/matches", { limit, offset });
977
+ return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
978
+ }
979
+ );
980
+
476
981
  // Start the server
477
982
  const transport = new StdioServerTransport();
478
983
  await server.connect(transport);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mentionova/mcp-server",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "MCP server for the Mentionova API - connect AI assistants to your AI search visibility data",
5
5
  "type": "module",
6
6
  "main": "index.js",