rc-ffs-mcp 1.0.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.
package/README.md ADDED
@@ -0,0 +1,231 @@
1
+ # RC FFS MCP Server
2
+
3
+ [![npm version](https://badge.fury.io/js/rc-ffs-mcp.svg)](https://www.npmjs.com/package/rc-ffs-mcp)
4
+
5
+ A Model Context Protocol (MCP) server for interacting with RingCentral Feature Flag Service (FFS).
6
+
7
+ ## Features
8
+
9
+ - **search_flag**: Search for feature flags by name (exact or fuzzy match)
10
+ - **list_flags**: List all feature flags with filtering options
11
+ - **create_flag**: Create new feature flags
12
+ - **update_flag**: Update flag properties (description, status, public)
13
+ - **update_rules**: Update or replace all rules for a flag
14
+ - **add_rule**: Add a single rule to an existing flag
15
+
16
+ ## Installation
17
+
18
+ ### Install from npm
19
+
20
+ ```bash
21
+ npm install -g rc-ffs-mcp
22
+ ```
23
+
24
+ Or use directly with npx:
25
+
26
+ ```bash
27
+ npx rc-ffs-mcp
28
+ ```
29
+
30
+ ### Install from source
31
+
32
+ ```bash
33
+ git clone https://github.com/ringcentral/rc-ffs-mcp.git
34
+ cd rc-ffs-mcp
35
+ npm install
36
+ npm run build
37
+ ```
38
+
39
+ ## Cursor IDE Configuration
40
+
41
+ Add the following to your Cursor MCP configuration file (`~/.cursor/mcp.json`):
42
+
43
+ ### Using npm global install
44
+
45
+ ```json
46
+ {
47
+ "mcpServers": {
48
+ "rc_ffs_mcp": {
49
+ "command": "rc-ffs-mcp",
50
+ "env": {
51
+ "FFS_BASE_URL": "http://your-ffs-server:8080"
52
+ }
53
+ }
54
+ }
55
+ }
56
+ ```
57
+
58
+ ### Using npx
59
+
60
+ ```json
61
+ {
62
+ "mcpServers": {
63
+ "rc_ffs_mcp": {
64
+ "command": "npx",
65
+ "args": ["-y", "rc-ffs-mcp"],
66
+ "env": {
67
+ "FFS_BASE_URL": "http://your-ffs-server:8080"
68
+ }
69
+ }
70
+ }
71
+ }
72
+ ```
73
+
74
+ ### Using local installation
75
+
76
+ ```json
77
+ {
78
+ "mcpServers": {
79
+ "rc_ffs_mcp": {
80
+ "command": "node",
81
+ "args": ["/path/to/rc-ffs-mcp/dist/index.js"],
82
+ "env": {
83
+ "FFS_BASE_URL": "http://your-ffs-server:8080"
84
+ }
85
+ }
86
+ }
87
+ }
88
+ ```
89
+
90
+ ## Environment Variables
91
+
92
+ | Variable | Description | Default |
93
+ |----------|-------------|---------|
94
+ | `FFS_BASE_URL` | Base URL of the FFS server | `http://aws16-c01-ffs01.ffs.svc.c01.eks02.k8s.aws16.lab.nordigy.ru:8080` |
95
+
96
+ ## Available Tools
97
+
98
+ ### 1. search_flag
99
+
100
+ Search for a feature flag by name.
101
+
102
+ **Parameters:**
103
+ - `name` (required): The name/ID of the feature flag
104
+ - `exact` (optional): If true, perform exact match. If false, perform fuzzy search (default: true)
105
+
106
+ **Example:**
107
+ ```json
108
+ {
109
+ "name": "my_feature_flag",
110
+ "exact": true
111
+ }
112
+ ```
113
+
114
+ ### 2. list_flags
115
+
116
+ List all feature flags with optional filtering.
117
+
118
+ **Parameters:**
119
+ - `limit` (optional): Maximum number of flags to return (default: 100)
120
+ - `statusFilter` (optional): Filter by status: "Active", "Inactive", "Archived", or "All" (default: "All")
121
+
122
+ **Example:**
123
+ ```json
124
+ {
125
+ "limit": 50,
126
+ "statusFilter": "Active"
127
+ }
128
+ ```
129
+
130
+ ### 3. create_flag
131
+
132
+ Create a new feature flag.
133
+
134
+ **Parameters:**
135
+ - `id` (required): Unique ID/name of the flag
136
+ - `dataType` (required): One of "Boolean", "Integer", "String", "JSON", "ListString", "ListInteger"
137
+ - `description` (optional): Description of the flag
138
+ - `status` (optional): Initial status: "Active", "Inactive", "Archived" (default: "Inactive")
139
+ - `public` (optional): Whether the flag is public (default: true)
140
+
141
+ **Example:**
142
+ ```json
143
+ {
144
+ "id": "my_new_flag",
145
+ "description": "My new feature flag",
146
+ "dataType": "Boolean",
147
+ "status": "Inactive",
148
+ "public": true
149
+ }
150
+ ```
151
+
152
+ ### 4. add_rule
153
+
154
+ Add a single rule to an existing feature flag.
155
+
156
+ **Parameters:**
157
+ - `flagId` (required): ID of the feature flag
158
+ - `value` (required): Value to return when rule matches
159
+ - `valueName` (optional): Name for the value
160
+ - `valueDescription` (optional): Description for the value
161
+ - `conditions` (required): Array of conditions
162
+
163
+ **Condition Properties:**
164
+ - `dimension`: One of "GlipUserId", "ExtensionId", "AccountId", "AppId", "BrandId", "EnvName", "EndpointId", "GlipCompanyId"
165
+ - `operator`: One of "Equal", "NotEqual", "Contains", "StartsWith", "EndsWith", "IsOneOf", "NotOneOf", "LessThan", "GreaterThan", etc.
166
+ - `argumentDataType`: "Integer", "String", or "ListString"
167
+ - `argument`: Value to compare against
168
+ - `description` (optional): Description of the condition
169
+
170
+ **Example:**
171
+ ```json
172
+ {
173
+ "flagId": "my_flag",
174
+ "value": "true",
175
+ "valueName": "enabled",
176
+ "conditions": [
177
+ {
178
+ "dimension": "AccountId",
179
+ "operator": "Equal",
180
+ "argumentDataType": "Integer",
181
+ "argument": "12345",
182
+ "description": "Enable for account 12345"
183
+ }
184
+ ]
185
+ }
186
+ ```
187
+
188
+ ### 5. update_rules
189
+
190
+ Replace all rules for a feature flag.
191
+
192
+ **Parameters:**
193
+ - `flagId` (required): ID of the feature flag
194
+ - `rules` (required): Array of rules
195
+
196
+ ### 6. update_flag
197
+
198
+ Update flag properties.
199
+
200
+ **Parameters:**
201
+ - `flagId` (required): ID of the feature flag
202
+ - `description` (optional): New description
203
+ - `status` (optional): New status
204
+ - `public` (optional): New public visibility
205
+
206
+ ## Supported Dimensions
207
+
208
+ - GlipUserId
209
+ - ExtensionId
210
+ - AccountId
211
+ - AppId
212
+ - BrandId
213
+ - EnvName
214
+ - EndpointId
215
+ - GlipCompanyId
216
+
217
+ ## Supported Operators
218
+
219
+ - Equal, NotEqual
220
+ - Contains, StartsWith, EndsWith
221
+ - NotStartsWith, NotEndsWith
222
+ - IsOneOf, NotOneOf
223
+ - LessThan, LessThanOrEqual
224
+ - GreaterThan, GreaterThanOrEqual
225
+ - SegmentMatch, NotSegmentMatch
226
+ - Percent
227
+ - SemVer comparisons (SemVerEqual, SemVerLessThan, etc.)
228
+
229
+ ## License
230
+
231
+ MIT
@@ -0,0 +1,103 @@
1
+ /**
2
+ * FFS API Types
3
+ */
4
+ export interface FFSCondition {
5
+ id?: string;
6
+ description?: string;
7
+ priority?: number;
8
+ dimension?: string;
9
+ operator: string;
10
+ argumentDataType?: string;
11
+ argument?: string;
12
+ }
13
+ export interface FFSValue {
14
+ id?: string;
15
+ name?: string;
16
+ description?: string;
17
+ value: string;
18
+ }
19
+ export interface FFSRule {
20
+ conditions: FFSCondition[];
21
+ value: FFSValue;
22
+ }
23
+ export interface FFSTag {
24
+ id: string;
25
+ accessControlId?: number;
26
+ }
27
+ export interface FFSFlag {
28
+ id: string;
29
+ description?: string;
30
+ creationTime?: string;
31
+ lastModifiedTime?: string;
32
+ effectiveFrom?: string;
33
+ public: boolean;
34
+ status: 'Active' | 'Inactive' | 'Archived';
35
+ dataType: 'Boolean' | 'Integer' | 'String' | 'JSON' | 'ListString' | 'ListInteger';
36
+ rules: FFSRule[];
37
+ tags?: FFSTag[];
38
+ }
39
+ export interface CreateFlagRequest {
40
+ id: string;
41
+ description?: string;
42
+ effectiveFrom?: string;
43
+ public?: boolean;
44
+ status?: 'Active' | 'Inactive' | 'Archived';
45
+ dataType: 'Boolean' | 'Integer' | 'String' | 'JSON' | 'ListString' | 'ListInteger';
46
+ rules?: FFSRule[];
47
+ }
48
+ export interface CreateRuleInput {
49
+ value: string;
50
+ valueName?: string;
51
+ valueDescription?: string;
52
+ conditions: Omit<FFSCondition, 'id'>[];
53
+ }
54
+ /**
55
+ * FFS API Client
56
+ */
57
+ export declare class FFSClient {
58
+ private client;
59
+ private baseUrl;
60
+ constructor(baseUrl?: string);
61
+ /**
62
+ * Get all flags
63
+ */
64
+ getAllFlags(): Promise<FFSFlag[]>;
65
+ /**
66
+ * Search flags by name (id)
67
+ */
68
+ searchFlag(name: string): Promise<FFSFlag | null>;
69
+ /**
70
+ * Search flags by pattern (fuzzy search)
71
+ */
72
+ searchFlagsByPattern(pattern: string): Promise<FFSFlag[]>;
73
+ /**
74
+ * Create a new flag
75
+ */
76
+ createFlag(request: CreateFlagRequest): Promise<FFSFlag>;
77
+ /**
78
+ * Remove read-only fields from flag data before update
79
+ * Note: creationTime must be null for updates, but lastModifiedTime is required
80
+ */
81
+ private removeReadOnlyFields;
82
+ /**
83
+ * Update a flag
84
+ */
85
+ updateFlag(flagId: string, updates: Partial<FFSFlag>): Promise<FFSFlag>;
86
+ /**
87
+ * Update or create rules for a flag
88
+ */
89
+ updateRules(flagId: string, rules: FFSRule[]): Promise<FFSFlag>;
90
+ /**
91
+ * Add a rule to a flag
92
+ */
93
+ addRule(flagId: string, ruleInput: CreateRuleInput): Promise<FFSFlag>;
94
+ /**
95
+ * Delete a flag
96
+ */
97
+ deleteFlag(flagId: string): Promise<void>;
98
+ /**
99
+ * Get server URL
100
+ */
101
+ getServerUrl(): string;
102
+ }
103
+ //# sourceMappingURL=ffs-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ffs-client.d.ts","sourceRoot":"","sources":["../src/ffs-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,158 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.FFSClient = void 0;
7
+ const axios_1 = __importDefault(require("axios"));
8
+ /**
9
+ * FFS API Client
10
+ */
11
+ class FFSClient {
12
+ constructor(baseUrl = 'http://aws16-c01-ffs01.ffs.svc.c01.eks02.k8s.aws16.lab.nordigy.ru:8080') {
13
+ this.baseUrl = baseUrl;
14
+ this.client = axios_1.default.create({
15
+ baseURL: `${baseUrl}/feature-flags/management/v1`,
16
+ headers: {
17
+ 'Content-Type': 'application/json',
18
+ },
19
+ timeout: 30000,
20
+ });
21
+ }
22
+ /**
23
+ * Get all flags
24
+ */
25
+ async getAllFlags() {
26
+ const response = await this.client.get('/flags/');
27
+ // API returns { flags: [...] }
28
+ return response.data.flags || [];
29
+ }
30
+ /**
31
+ * Search flags by name (id)
32
+ */
33
+ async searchFlag(name) {
34
+ try {
35
+ const response = await this.client.get(`/flags/${encodeURIComponent(name)}/`);
36
+ return response.data;
37
+ }
38
+ catch (error) {
39
+ if (error.response?.status === 404) {
40
+ return null;
41
+ }
42
+ throw error;
43
+ }
44
+ }
45
+ /**
46
+ * Search flags by pattern (fuzzy search)
47
+ */
48
+ async searchFlagsByPattern(pattern) {
49
+ const allFlags = await this.getAllFlags();
50
+ const lowerPattern = pattern.toLowerCase();
51
+ return allFlags.filter(flag => flag.id.toLowerCase().includes(lowerPattern));
52
+ }
53
+ /**
54
+ * Create a new flag
55
+ */
56
+ async createFlag(request) {
57
+ const payload = {
58
+ id: request.id,
59
+ description: request.description || '',
60
+ effectiveFrom: request.effectiveFrom || null,
61
+ public: request.public ?? true,
62
+ status: request.status || 'Inactive',
63
+ dataType: request.dataType,
64
+ rules: request.rules || [],
65
+ };
66
+ const response = await this.client.post('/flags/', payload);
67
+ return response.data;
68
+ }
69
+ /**
70
+ * Remove read-only fields from flag data before update
71
+ * Note: creationTime must be null for updates, but lastModifiedTime is required
72
+ */
73
+ removeReadOnlyFields(flag) {
74
+ const { creationTime, ...writableFields } = flag;
75
+ return writableFields;
76
+ }
77
+ /**
78
+ * Update a flag
79
+ */
80
+ async updateFlag(flagId, updates) {
81
+ // First get the existing flag
82
+ const existingFlag = await this.searchFlag(flagId);
83
+ if (!existingFlag) {
84
+ throw new Error(`Flag '${flagId}' not found`);
85
+ }
86
+ // Merge updates with existing data and remove read-only fields
87
+ const updatedFlag = this.removeReadOnlyFields({
88
+ ...existingFlag,
89
+ ...updates,
90
+ id: flagId, // Ensure ID doesn't change
91
+ });
92
+ const response = await this.client.put(`/flags/${encodeURIComponent(flagId)}/`, updatedFlag);
93
+ return response.data;
94
+ }
95
+ /**
96
+ * Update or create rules for a flag
97
+ */
98
+ async updateRules(flagId, rules) {
99
+ const existingFlag = await this.searchFlag(flagId);
100
+ if (!existingFlag) {
101
+ throw new Error(`Flag '${flagId}' not found`);
102
+ }
103
+ // Update the flag with new rules and remove read-only fields
104
+ const updatedFlag = this.removeReadOnlyFields({
105
+ ...existingFlag,
106
+ rules: rules,
107
+ });
108
+ const response = await this.client.put(`/flags/${encodeURIComponent(flagId)}/`, updatedFlag);
109
+ return response.data;
110
+ }
111
+ /**
112
+ * Add a rule to a flag
113
+ */
114
+ async addRule(flagId, ruleInput) {
115
+ const existingFlag = await this.searchFlag(flagId);
116
+ if (!existingFlag) {
117
+ throw new Error(`Flag '${flagId}' not found`);
118
+ }
119
+ // Calculate next priority for conditions
120
+ let maxPriority = 0;
121
+ existingFlag.rules.forEach(rule => {
122
+ rule.conditions.forEach(cond => {
123
+ if (cond.priority && cond.priority > maxPriority) {
124
+ maxPriority = cond.priority;
125
+ }
126
+ });
127
+ });
128
+ // Create conditions with priorities
129
+ const conditions = ruleInput.conditions.map((cond, idx) => ({
130
+ ...cond,
131
+ priority: maxPriority + idx + 1,
132
+ }));
133
+ const newRule = {
134
+ conditions,
135
+ value: {
136
+ name: ruleInput.valueName || ruleInput.value,
137
+ description: ruleInput.valueDescription || '',
138
+ value: ruleInput.value,
139
+ },
140
+ };
141
+ const updatedRules = [...existingFlag.rules, newRule];
142
+ return this.updateRules(flagId, updatedRules);
143
+ }
144
+ /**
145
+ * Delete a flag
146
+ */
147
+ async deleteFlag(flagId) {
148
+ await this.client.delete(`/flags/${encodeURIComponent(flagId)}/`);
149
+ }
150
+ /**
151
+ * Get server URL
152
+ */
153
+ getServerUrl() {
154
+ return this.baseUrl;
155
+ }
156
+ }
157
+ exports.FFSClient = FFSClient;
158
+ //# sourceMappingURL=ffs-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ffs-client.js","sourceRoot":"","sources":["../src/ffs-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,404 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
5
+ const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
6
+ const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
7
+ const ffs_client_js_1 = require("./ffs-client.js");
8
+ // Initialize FFS client with default URL
9
+ const FFS_BASE_URL = process.env.FFS_BASE_URL || 'http://aws16-c01-ffs01.ffs.svc.c01.eks02.k8s.aws16.lab.nordigy.ru:8080';
10
+ const ffsClient = new ffs_client_js_1.FFSClient(FFS_BASE_URL);
11
+ // Define available tools
12
+ const tools = [
13
+ {
14
+ name: 'search_flag',
15
+ description: 'Search for a feature flag by name (exact match or pattern). Returns the flag details including rules and conditions.',
16
+ inputSchema: {
17
+ type: 'object',
18
+ properties: {
19
+ name: {
20
+ type: 'string',
21
+ description: 'The name/ID of the feature flag to search for. Can be exact name or a pattern for fuzzy search.',
22
+ },
23
+ exact: {
24
+ type: 'boolean',
25
+ description: 'If true, perform exact match. If false, perform fuzzy search (default: true).',
26
+ default: true,
27
+ },
28
+ },
29
+ required: ['name'],
30
+ },
31
+ },
32
+ {
33
+ name: 'list_flags',
34
+ description: 'List all feature flags with summary information including id, status, dataType, and values count.',
35
+ inputSchema: {
36
+ type: 'object',
37
+ properties: {
38
+ limit: {
39
+ type: 'number',
40
+ description: 'Maximum number of flags to return (default: 100)',
41
+ default: 100,
42
+ },
43
+ statusFilter: {
44
+ type: 'string',
45
+ enum: ['Active', 'Inactive', 'Archived', 'All'],
46
+ description: 'Filter flags by status (default: All)',
47
+ default: 'All',
48
+ },
49
+ },
50
+ },
51
+ },
52
+ {
53
+ name: 'create_flag',
54
+ description: 'Create a new feature flag with the specified name and configuration.',
55
+ inputSchema: {
56
+ type: 'object',
57
+ properties: {
58
+ id: {
59
+ type: 'string',
60
+ description: 'The unique ID/name of the feature flag.',
61
+ },
62
+ description: {
63
+ type: 'string',
64
+ description: 'Description of the feature flag.',
65
+ },
66
+ dataType: {
67
+ type: 'string',
68
+ enum: ['Boolean', 'Integer', 'String', 'JSON', 'ListString', 'ListInteger'],
69
+ description: 'The data type of the flag value.',
70
+ },
71
+ status: {
72
+ type: 'string',
73
+ enum: ['Active', 'Inactive', 'Archived'],
74
+ description: 'Initial status of the flag (default: Inactive).',
75
+ default: 'Inactive',
76
+ },
77
+ public: {
78
+ type: 'boolean',
79
+ description: 'Whether the flag is public (default: true).',
80
+ default: true,
81
+ },
82
+ defaultValue: {
83
+ type: 'string',
84
+ description: 'The default value for the flag.',
85
+ },
86
+ },
87
+ required: ['id', 'dataType'],
88
+ },
89
+ },
90
+ {
91
+ name: 'update_rules',
92
+ description: 'Update or create rules for a specific feature flag. This replaces all existing rules with the provided ones.',
93
+ inputSchema: {
94
+ type: 'object',
95
+ properties: {
96
+ flagId: {
97
+ type: 'string',
98
+ description: 'The ID of the feature flag to update.',
99
+ },
100
+ rules: {
101
+ type: 'array',
102
+ description: 'Array of rules to set for the flag.',
103
+ items: {
104
+ type: 'object',
105
+ properties: {
106
+ priority: {
107
+ type: 'number',
108
+ description: 'Priority of the rule (lower = higher priority).',
109
+ },
110
+ value: {
111
+ type: 'string',
112
+ description: 'The value to return when this rule matches.',
113
+ },
114
+ conditions: {
115
+ type: 'array',
116
+ description: 'Array of conditions for this rule (AND logic).',
117
+ items: {
118
+ type: 'object',
119
+ properties: {
120
+ description: {
121
+ type: 'string',
122
+ description: 'Description of the condition.',
123
+ },
124
+ dimension: {
125
+ type: 'string',
126
+ enum: ['GlipUserId', 'ExtensionId', 'AccountId', 'AppId', 'BrandId', 'EnvName', 'EndpointId', 'GlipCompanyId'],
127
+ description: 'The dimension to evaluate.',
128
+ },
129
+ customDimension: {
130
+ type: 'string',
131
+ description: 'Custom dimension name (if dimension is not specified).',
132
+ },
133
+ operator: {
134
+ type: 'string',
135
+ enum: ['Equal', 'NotEqual', 'Contains', 'StartsWith', 'EndsWith', 'NotStartsWith', 'NotEndsWith', 'IsOneOf', 'NotOneOf', 'LessThan', 'LessThanOrEqual', 'GreaterThan', 'GreaterThanOrEqual', 'SegmentMatch', 'NotSegmentMatch', 'Percent', 'SemVerEqual', 'NotSemVerEqual', 'SemVerLessThan', 'SemVerLessThanOrEqual', 'SemVerGreaterThan', 'SemVerGreaterThanOrEqual'],
136
+ description: 'The comparison operator.',
137
+ },
138
+ argumentDataType: {
139
+ type: 'string',
140
+ enum: ['Integer', 'String'],
141
+ description: 'Data type of the argument.',
142
+ },
143
+ argument: {
144
+ type: 'string',
145
+ description: 'The value to compare against.',
146
+ },
147
+ },
148
+ required: ['operator', 'argumentDataType', 'argument'],
149
+ },
150
+ },
151
+ },
152
+ required: ['priority', 'value', 'conditions'],
153
+ },
154
+ },
155
+ },
156
+ required: ['flagId', 'rules'],
157
+ },
158
+ },
159
+ {
160
+ name: 'add_rule',
161
+ description: 'Add a single rule to an existing feature flag without removing existing rules.',
162
+ inputSchema: {
163
+ type: 'object',
164
+ properties: {
165
+ flagId: {
166
+ type: 'string',
167
+ description: 'The ID of the feature flag.',
168
+ },
169
+ value: {
170
+ type: 'string',
171
+ description: 'The value to return when this rule matches.',
172
+ },
173
+ valueName: {
174
+ type: 'string',
175
+ description: 'Optional name for the value.',
176
+ },
177
+ valueDescription: {
178
+ type: 'string',
179
+ description: 'Optional description for the value.',
180
+ },
181
+ conditions: {
182
+ type: 'array',
183
+ description: 'Array of conditions for this rule.',
184
+ items: {
185
+ type: 'object',
186
+ properties: {
187
+ description: {
188
+ type: 'string',
189
+ },
190
+ dimension: {
191
+ type: 'string',
192
+ enum: ['GlipUserId', 'ExtensionId', 'AccountId', 'AppId', 'BrandId', 'EnvName', 'EndpointId', 'GlipCompanyId'],
193
+ },
194
+ operator: {
195
+ type: 'string',
196
+ enum: ['Equal', 'NotEqual', 'Contains', 'StartsWith', 'EndsWith', 'NotStartsWith', 'NotEndsWith', 'IsOneOf', 'NotOneOf', 'LessThan', 'LessThanOrEqual', 'GreaterThan', 'GreaterThanOrEqual', 'SegmentMatch', 'NotSegmentMatch', 'Percent', 'SemVerEqual', 'NotSemVerEqual', 'SemVerLessThan', 'SemVerLessThanOrEqual', 'SemVerGreaterThan', 'SemVerGreaterThanOrEqual'],
197
+ },
198
+ argumentDataType: {
199
+ type: 'string',
200
+ enum: ['Integer', 'String', 'ListString'],
201
+ },
202
+ argument: {
203
+ type: 'string',
204
+ },
205
+ },
206
+ required: ['operator', 'argumentDataType', 'argument'],
207
+ },
208
+ },
209
+ },
210
+ required: ['flagId', 'value', 'conditions'],
211
+ },
212
+ },
213
+ {
214
+ name: 'update_flag',
215
+ description: 'Update flag properties like description, status, public visibility, or default value.',
216
+ inputSchema: {
217
+ type: 'object',
218
+ properties: {
219
+ flagId: {
220
+ type: 'string',
221
+ description: 'The ID of the feature flag to update.',
222
+ },
223
+ description: {
224
+ type: 'string',
225
+ description: 'New description for the flag.',
226
+ },
227
+ status: {
228
+ type: 'string',
229
+ enum: ['Active', 'Inactive', 'Archived'],
230
+ description: 'New status for the flag.',
231
+ },
232
+ public: {
233
+ type: 'boolean',
234
+ description: 'Whether the flag should be public.',
235
+ },
236
+ defaultValue: {
237
+ type: 'string',
238
+ description: 'New default value for the flag.',
239
+ },
240
+ },
241
+ required: ['flagId'],
242
+ },
243
+ },
244
+ ];
245
+ // Create MCP server
246
+ const server = new index_js_1.Server({
247
+ name: 'rc_ffs_mcp',
248
+ version: '1.0.0',
249
+ }, {
250
+ capabilities: {
251
+ tools: {},
252
+ },
253
+ });
254
+ // Handle list tools request
255
+ server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => {
256
+ return { tools };
257
+ });
258
+ // Handle tool calls
259
+ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
260
+ const { name, arguments: args } = request.params;
261
+ try {
262
+ switch (name) {
263
+ case 'search_flag': {
264
+ const { name: flagName, exact = true } = args;
265
+ if (exact) {
266
+ const flag = await ffsClient.searchFlag(flagName);
267
+ if (flag) {
268
+ return {
269
+ content: [
270
+ {
271
+ type: 'text',
272
+ text: JSON.stringify(flag, null, 2),
273
+ },
274
+ ],
275
+ };
276
+ }
277
+ else {
278
+ return {
279
+ content: [
280
+ {
281
+ type: 'text',
282
+ text: `Flag '${flagName}' not found.`,
283
+ },
284
+ ],
285
+ };
286
+ }
287
+ }
288
+ else {
289
+ const flags = await ffsClient.searchFlagsByPattern(flagName);
290
+ return {
291
+ content: [
292
+ {
293
+ type: 'text',
294
+ text: `Found ${flags.length} flags matching '${flagName}':\n${JSON.stringify(flags, null, 2)}`,
295
+ },
296
+ ],
297
+ };
298
+ }
299
+ }
300
+ case 'list_flags': {
301
+ const { limit = 100, statusFilter = 'All' } = args;
302
+ let flags = await ffsClient.getAllFlags();
303
+ if (statusFilter !== 'All') {
304
+ flags = flags.filter(f => f.status === statusFilter);
305
+ }
306
+ flags = flags.slice(0, limit);
307
+ return {
308
+ content: [
309
+ {
310
+ type: 'text',
311
+ text: `Found ${flags.length} flags:\n${JSON.stringify(flags, null, 2)}`,
312
+ },
313
+ ],
314
+ };
315
+ }
316
+ case 'create_flag': {
317
+ const createRequest = args;
318
+ const newFlag = await ffsClient.createFlag(createRequest);
319
+ return {
320
+ content: [
321
+ {
322
+ type: 'text',
323
+ text: `Successfully created flag '${newFlag.id}':\n${JSON.stringify(newFlag, null, 2)}`,
324
+ },
325
+ ],
326
+ };
327
+ }
328
+ case 'update_rules': {
329
+ const { flagId, rules } = args;
330
+ const updatedFlag = await ffsClient.updateRules(flagId, rules);
331
+ return {
332
+ content: [
333
+ {
334
+ type: 'text',
335
+ text: `Successfully updated rules for flag '${flagId}':\n${JSON.stringify(updatedFlag, null, 2)}`,
336
+ },
337
+ ],
338
+ };
339
+ }
340
+ case 'add_rule': {
341
+ const { flagId, value, valueName, valueDescription, conditions } = args;
342
+ const ruleInput = {
343
+ value,
344
+ valueName,
345
+ valueDescription,
346
+ conditions,
347
+ };
348
+ const updatedFlag = await ffsClient.addRule(flagId, ruleInput);
349
+ return {
350
+ content: [
351
+ {
352
+ type: 'text',
353
+ text: `Successfully added rule to flag '${flagId}':\n${JSON.stringify(updatedFlag, null, 2)}`,
354
+ },
355
+ ],
356
+ };
357
+ }
358
+ case 'update_flag': {
359
+ const { flagId, ...updates } = args;
360
+ const updatedFlag = await ffsClient.updateFlag(flagId, updates);
361
+ return {
362
+ content: [
363
+ {
364
+ type: 'text',
365
+ text: `Successfully updated flag '${flagId}':\n${JSON.stringify(updatedFlag, null, 2)}`,
366
+ },
367
+ ],
368
+ };
369
+ }
370
+ default:
371
+ return {
372
+ content: [
373
+ {
374
+ type: 'text',
375
+ text: `Unknown tool: ${name}`,
376
+ },
377
+ ],
378
+ isError: true,
379
+ };
380
+ }
381
+ }
382
+ catch (error) {
383
+ return {
384
+ content: [
385
+ {
386
+ type: 'text',
387
+ text: `Error: ${error.message || String(error)}`,
388
+ },
389
+ ],
390
+ isError: true,
391
+ };
392
+ }
393
+ });
394
+ // Start the server
395
+ async function main() {
396
+ const transport = new stdio_js_1.StdioServerTransport();
397
+ await server.connect(transport);
398
+ console.error('RC FFS MCP server started');
399
+ }
400
+ main().catch((error) => {
401
+ console.error('Fatal error:', error);
402
+ process.exit(1);
403
+ });
404
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "rc-ffs-mcp",
3
+ "version": "1.0.0",
4
+ "description": "MCP server for RingCentral Feature Flag Service (FFS) - provides tools to search, create, and manage feature flags",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "bin": {
8
+ "rc-ffs-mcp": "./dist/index.js"
9
+ },
10
+ "files": [
11
+ "dist",
12
+ "README.md"
13
+ ],
14
+ "scripts": {
15
+ "build": "tsc",
16
+ "start": "node dist/index.js",
17
+ "dev": "ts-node src/index.ts",
18
+ "prepublishOnly": "npm run build",
19
+ "test": "node test-client.js"
20
+ },
21
+ "keywords": [
22
+ "mcp",
23
+ "model-context-protocol",
24
+ "ringcentral",
25
+ "ffs",
26
+ "feature-flags",
27
+ "feature-toggle",
28
+ "cursor",
29
+ "ai",
30
+ "llm"
31
+ ],
32
+ "author": "RingCentral",
33
+ "license": "MIT",
34
+ "repository": {
35
+ "type": "git",
36
+ "url": "https://github.com/ringcentral/rc-ffs-mcp"
37
+ },
38
+ "homepage": "https://github.com/ringcentral/rc-ffs-mcp#readme",
39
+ "bugs": {
40
+ "url": "https://github.com/ringcentral/rc-ffs-mcp/issues"
41
+ },
42
+ "engines": {
43
+ "node": ">=18.0.0"
44
+ },
45
+ "dependencies": {
46
+ "@modelcontextprotocol/sdk": "^1.0.0",
47
+ "axios": "^1.6.0"
48
+ },
49
+ "devDependencies": {
50
+ "@types/node": "^20.10.0",
51
+ "typescript": "^5.3.0",
52
+ "ts-node": "^10.9.0"
53
+ }
54
+ }