@flowrelay/mcp-server 1.0.1 → 1.0.3
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 +4 -2
- package/dist/api.d.ts +15 -1
- package/dist/api.js +2 -2
- package/dist/index.js +12 -14
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@ It connects to Flow Relay API v1 using an API key and supports:
|
|
|
9
9
|
## Package
|
|
10
10
|
|
|
11
11
|
- Name: @flowrelay/mcp-server
|
|
12
|
-
- Version: 1.0.
|
|
12
|
+
- Version: 1.0.3
|
|
13
13
|
|
|
14
14
|
## What Is Included
|
|
15
15
|
|
|
@@ -18,12 +18,14 @@ The server currently exposes these tools:
|
|
|
18
18
|
- get_workspace_context
|
|
19
19
|
- list_projects
|
|
20
20
|
- set_active_project
|
|
21
|
-
- list_filter_options (lists the selectable resources, branches, event types and priorities per source for a project – call this before generating so handoff/insight filters use real values instead of guesses)
|
|
21
|
+
- list_filter_options (lists the selectable resources, branches, event types and priorities per source for a project – call this before generating so handoff/insight filters use real values instead of guesses; also reports whether Figma is selectable, since Figma requires the project's processing region to be Global)
|
|
22
22
|
- list_handoffs (returns project-specific handoffs, or an aggregated view of all accessible project handoffs if no project is active; filter by status: active, archived, or all)
|
|
23
23
|
- generate_handoff (processed asynchronously, and the server automatically polls until the job finishes. Requires active project or project_id. Accepts per-source filters: projects, eventTypes, branches, priorities.)
|
|
24
24
|
- generate_correlation_insight (accepts per-source filters)
|
|
25
25
|
- generate_onboarding_brief (accepts per-source filters)
|
|
26
26
|
- generate_architecture_insight (accepts per-source filters)
|
|
27
|
+
|
|
28
|
+
Selecting Figma in `sources` or `filters` attaches visual context to the generation (rendered frame previews plus the indexed design scene: layout, texts, prototype flows). It works on projects whose processing region is Global and adds a flat 1-credit surcharge per generation.
|
|
27
29
|
- list_insights
|
|
28
30
|
- list_integrations
|
|
29
31
|
- list_events
|
package/dist/api.d.ts
CHANGED
|
@@ -58,6 +58,8 @@ export interface HandoffResult {
|
|
|
58
58
|
next_steps: string[];
|
|
59
59
|
created_at: string;
|
|
60
60
|
updated_at?: string;
|
|
61
|
+
/** Canonical Markdown rendered server-side – identical to the dashboard copy button. */
|
|
62
|
+
markdown?: string;
|
|
61
63
|
}
|
|
62
64
|
export interface InsightResult {
|
|
63
65
|
id: string;
|
|
@@ -77,6 +79,8 @@ export interface InsightResult {
|
|
|
77
79
|
related_event_ids: string[];
|
|
78
80
|
created_at: string;
|
|
79
81
|
updated_at?: string;
|
|
82
|
+
/** Canonical Markdown rendered server-side – identical to the dashboard copy button. */
|
|
83
|
+
markdown?: string;
|
|
80
84
|
}
|
|
81
85
|
export interface UntrackedResource {
|
|
82
86
|
source: string;
|
|
@@ -122,6 +126,13 @@ export interface AvailableSourceFilter {
|
|
|
122
126
|
}[];
|
|
123
127
|
}
|
|
124
128
|
export type AvailableFilters = Record<string, AvailableSourceFilter>;
|
|
129
|
+
export interface FigmaGateInfo {
|
|
130
|
+
selectable: boolean;
|
|
131
|
+
region: string;
|
|
132
|
+
scope: string;
|
|
133
|
+
canManageResidency: boolean;
|
|
134
|
+
residencyHref: string | null;
|
|
135
|
+
}
|
|
125
136
|
export declare class FlowRelayAPI {
|
|
126
137
|
private baseUrl;
|
|
127
138
|
private apiKey;
|
|
@@ -129,7 +140,10 @@ export declare class FlowRelayAPI {
|
|
|
129
140
|
private requestRaw;
|
|
130
141
|
private request;
|
|
131
142
|
listProjects(): Promise<TenantContext>;
|
|
132
|
-
getHandoffFilters(projectId: string): Promise<
|
|
143
|
+
getHandoffFilters(projectId: string): Promise<{
|
|
144
|
+
filters: AvailableFilters;
|
|
145
|
+
figma: FigmaGateInfo | null;
|
|
146
|
+
}>;
|
|
133
147
|
listHandoffs(status?: string, limit?: number, projectId?: string | null): Promise<{
|
|
134
148
|
handoffs: HandoffResult[];
|
|
135
149
|
}>;
|
package/dist/api.js
CHANGED
|
@@ -35,8 +35,8 @@ export class FlowRelayAPI {
|
|
|
35
35
|
return this.request('/projects');
|
|
36
36
|
}
|
|
37
37
|
async getHandoffFilters(projectId) {
|
|
38
|
-
const { filters } = await this.request(`/handoffs/filters?project_id=${encodeURIComponent(projectId)}`);
|
|
39
|
-
return filters ?? {};
|
|
38
|
+
const { filters, figma } = await this.request(`/handoffs/filters?project_id=${encodeURIComponent(projectId)}`);
|
|
39
|
+
return { filters: filters ?? {}, figma: figma ?? null };
|
|
40
40
|
}
|
|
41
41
|
async listHandoffs(status = 'active', limit = 10, projectId) {
|
|
42
42
|
const params = new URLSearchParams();
|
package/dist/index.js
CHANGED
|
@@ -222,16 +222,8 @@ server.tool('generate_handoff', 'Generate a new context handoff for personal sco
|
|
|
222
222
|
return { content: [{ type: 'text', text: `Could not generate handoff: ${reason}` }] };
|
|
223
223
|
}
|
|
224
224
|
const handoff = result;
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
text += `\n**Project:** ${handoff.project_name}\n`;
|
|
228
|
-
text += `\n**Sources:** ${handoff.sources.join(', ')}\n`;
|
|
229
|
-
if (handoff.key_changes?.length)
|
|
230
|
-
text += `\n**Key changes:**\n${handoff.key_changes.map((c) => `- ${c}`).join('\n')}\n`;
|
|
231
|
-
if (handoff.decisions.length)
|
|
232
|
-
text += `\n**Decisions:**\n${handoff.decisions.map((d) => `- ${d}`).join('\n')}\n`;
|
|
233
|
-
if (handoff.next_steps.length)
|
|
234
|
-
text += `\n**Next steps:**\n${handoff.next_steps.map((s) => `- ${s}`).join('\n')}\n`;
|
|
225
|
+
// Server renders the canonical Markdown; fall back for pre-markdown servers.
|
|
226
|
+
const text = handoff.markdown ?? `# ${handoff.title}\n\n${handoff.summary}\n`;
|
|
235
227
|
return { content: [{ type: 'text', text }] };
|
|
236
228
|
}
|
|
237
229
|
catch (err) {
|
|
@@ -369,7 +361,7 @@ server.tool('generate_correlation_insight', 'Generate a cross-source correlation
|
|
|
369
361
|
return { content: [{ type: 'text', text: `Could not generate correlation insight: ${reason}` }] };
|
|
370
362
|
}
|
|
371
363
|
const insight = result;
|
|
372
|
-
return { content: [{ type: 'text', text: `# ${insight.title}\n\n${insight.summary}` }] };
|
|
364
|
+
return { content: [{ type: 'text', text: insight.markdown ?? `# ${insight.title}\n\n${insight.summary}` }] };
|
|
373
365
|
}
|
|
374
366
|
catch (err) {
|
|
375
367
|
return { content: [{ type: 'text', text: `Failed: ${err.message}` }] };
|
|
@@ -400,7 +392,7 @@ server.tool('generate_onboarding_brief', 'Generate an onboarding brief AI insigh
|
|
|
400
392
|
return { content: [{ type: 'text', text: `Could not generate onboarding brief: ${reason}` }] };
|
|
401
393
|
}
|
|
402
394
|
const insight = result;
|
|
403
|
-
return { content: [{ type: 'text', text: `# ${insight.title}\n\n${insight.summary}` }] };
|
|
395
|
+
return { content: [{ type: 'text', text: insight.markdown ?? `# ${insight.title}\n\n${insight.summary}` }] };
|
|
404
396
|
}
|
|
405
397
|
catch (err) {
|
|
406
398
|
return { content: [{ type: 'text', text: `Failed: ${err.message}` }] };
|
|
@@ -429,7 +421,7 @@ server.tool('generate_architecture_insight', 'Generate an architecture insight A
|
|
|
429
421
|
return { content: [{ type: 'text', text: `Could not generate architecture insight: ${reason}` }] };
|
|
430
422
|
}
|
|
431
423
|
const insight = result;
|
|
432
|
-
return { content: [{ type: 'text', text: `# ${insight.title}\n\n${insight.summary}` }] };
|
|
424
|
+
return { content: [{ type: 'text', text: insight.markdown ?? `# ${insight.title}\n\n${insight.summary}` }] };
|
|
433
425
|
}
|
|
434
426
|
catch (err) {
|
|
435
427
|
return { content: [{ type: 'text', text: `Failed: ${err.message}` }] };
|
|
@@ -462,7 +454,7 @@ server.tool('list_filter_options', 'List the real per-source filter values (reso
|
|
|
462
454
|
}, async ({ project_id }) => {
|
|
463
455
|
try {
|
|
464
456
|
const resolved = await requireProject(project_id);
|
|
465
|
-
const filters = await api.getHandoffFilters(resolved.projectId);
|
|
457
|
+
const { filters, figma } = await api.getHandoffFilters(resolved.projectId);
|
|
466
458
|
const sources = Object.keys(filters);
|
|
467
459
|
if (sources.length === 0) {
|
|
468
460
|
return { content: [{ type: 'text', text: `No connected sources with filter options for ${resolved.project.name}.` }] };
|
|
@@ -483,6 +475,12 @@ server.tool('list_filter_options', 'List the real per-source filter values (reso
|
|
|
483
475
|
lines.push(`- Priorities: ${f.priorities.map((p) => p.value).join(', ')}`);
|
|
484
476
|
return lines.join('\n');
|
|
485
477
|
});
|
|
478
|
+
if (figma && !figma.selectable) {
|
|
479
|
+
blocks.push('### figma\n- NOT selectable on this project: Figma visual context requires the Global processing region. ' +
|
|
480
|
+
(figma.canManageResidency
|
|
481
|
+
? 'Switch the project to Global in its Data Residency settings first.'
|
|
482
|
+
: 'Ask an organization admin to switch the project to Global first.'));
|
|
483
|
+
}
|
|
486
484
|
return { content: [{ type: 'text', text: `Filter options for ${resolved.project.name}:\n\n${blocks.join('\n\n')}` }] };
|
|
487
485
|
}
|
|
488
486
|
catch (err) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flowrelay/mcp-server",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "Flow Relay MCP Server for Claude Desktop and Claude Code – handoffs, integrations, and context events via natural conversation.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|