@fruition/fcp-mcp-server 1.27.0 → 1.27.1
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/dist/index.js +42 -4
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -203,6 +203,9 @@ const TOOL_PERMISSIONS = {
|
|
|
203
203
|
// Resolved role for the current API key. Cached only on successful lookup so
|
|
204
204
|
// transient FCP outages don't pin us to 'none' for the rest of the session.
|
|
205
205
|
let cachedUserRole;
|
|
206
|
+
// The API key owner's email, as reported by /api/mcp/me. Used as the fallback
|
|
207
|
+
// identity for "my"-scoped queries when FCP_USER_EMAIL is not configured.
|
|
208
|
+
let cachedUserEmail;
|
|
206
209
|
async function fetchUserRole() {
|
|
207
210
|
if (cachedUserRole !== undefined)
|
|
208
211
|
return cachedUserRole;
|
|
@@ -227,6 +230,8 @@ async function fetchUserRole() {
|
|
|
227
230
|
const data = await res.json();
|
|
228
231
|
const role = data?.role ?? 'none';
|
|
229
232
|
cachedUserRole = role;
|
|
233
|
+
if (data?.email)
|
|
234
|
+
cachedUserEmail = data.email;
|
|
230
235
|
console.error(`[MCP Server] Resolved user role: ${role} (${data?.email ?? 'unknown'})`);
|
|
231
236
|
return role;
|
|
232
237
|
}
|
|
@@ -235,6 +240,17 @@ async function fetchUserRole() {
|
|
|
235
240
|
return 'none';
|
|
236
241
|
}
|
|
237
242
|
}
|
|
243
|
+
// Resolve the acting user's email for "my"-scoped queries (e.g. unroo_get_my_tasks).
|
|
244
|
+
// Precedence: FCP_USER_EMAIL (the per-developer identity) -> the API key owner's
|
|
245
|
+
// email from /api/mcp/me (the shared key's creator, honoring the "based on API
|
|
246
|
+
// key" contract). Returns '' if neither resolves, so callers can surface a clear
|
|
247
|
+
// "set FCP_USER_EMAIL" message rather than silently returning the org-wide list.
|
|
248
|
+
async function resolveActingEmail() {
|
|
249
|
+
if (FCP_USER_EMAIL)
|
|
250
|
+
return FCP_USER_EMAIL;
|
|
251
|
+
await fetchUserRole(); // populates cachedUserEmail as a side effect
|
|
252
|
+
return cachedUserEmail ?? '';
|
|
253
|
+
}
|
|
238
254
|
function isRoleAtLeast(actual, required) {
|
|
239
255
|
if (actual === 'none')
|
|
240
256
|
return required === 'none';
|
|
@@ -2051,17 +2067,17 @@ const TOOLS = [
|
|
|
2051
2067
|
},
|
|
2052
2068
|
{
|
|
2053
2069
|
name: 'unroo_get_my_tasks',
|
|
2054
|
-
description: 'Get tasks assigned to
|
|
2070
|
+
description: 'Get tasks assigned to you. "You" resolves from FCP_USER_EMAIL (your Fruition email), falling back to the FCP API key owner if FCP_USER_EMAIL is unset. Returns an error asking you to set FCP_USER_EMAIL if neither can be resolved.',
|
|
2055
2071
|
inputSchema: {
|
|
2056
2072
|
type: 'object',
|
|
2057
2073
|
properties: {
|
|
2058
2074
|
status: {
|
|
2059
2075
|
type: 'string',
|
|
2060
|
-
description: 'Filter by status (comma-separated for multiple)',
|
|
2076
|
+
description: 'Filter by status: To Do, In Progress, Done, Blocked (case-sensitive, comma-separated for multiple)',
|
|
2061
2077
|
},
|
|
2062
2078
|
limit: {
|
|
2063
2079
|
type: 'number',
|
|
2064
|
-
description: 'Maximum number of tasks to return',
|
|
2080
|
+
description: 'Maximum number of tasks to return (default 50)',
|
|
2065
2081
|
},
|
|
2066
2082
|
},
|
|
2067
2083
|
},
|
|
@@ -4425,9 +4441,30 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4425
4441
|
}
|
|
4426
4442
|
case 'unroo_get_my_tasks': {
|
|
4427
4443
|
const { status, limit } = args;
|
|
4428
|
-
//
|
|
4444
|
+
// "My tasks" must be scoped by an explicit assignee_email filter. There is
|
|
4445
|
+
// NO server-side auto-scoping: GET /api/external/fcp/tasks returns every
|
|
4446
|
+
// task unless assignee_email is supplied, and the shared FCP_API_TOKEN
|
|
4447
|
+
// resolves to the key creator (not the developer running Claude Code), so
|
|
4448
|
+
// the key alone cannot identify "me". Resolve the acting user's email and
|
|
4449
|
+
// pass it as the filter.
|
|
4450
|
+
const assignee_email = await resolveActingEmail();
|
|
4451
|
+
if (!assignee_email) {
|
|
4452
|
+
return {
|
|
4453
|
+
content: [
|
|
4454
|
+
{
|
|
4455
|
+
type: 'text',
|
|
4456
|
+
text: JSON.stringify({
|
|
4457
|
+
total: 0,
|
|
4458
|
+
tasks: [],
|
|
4459
|
+
error: 'Could not determine your identity. Set FCP_USER_EMAIL (your Fruition email) in your MCP server env config so "my tasks" can be scoped to you.',
|
|
4460
|
+
}, null, 2),
|
|
4461
|
+
},
|
|
4462
|
+
],
|
|
4463
|
+
};
|
|
4464
|
+
}
|
|
4429
4465
|
const result = await unrooClient.listTasks({
|
|
4430
4466
|
status,
|
|
4467
|
+
assignee_email,
|
|
4431
4468
|
limit: limit || 50,
|
|
4432
4469
|
});
|
|
4433
4470
|
return {
|
|
@@ -4436,6 +4473,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4436
4473
|
type: 'text',
|
|
4437
4474
|
text: JSON.stringify({
|
|
4438
4475
|
total: result.tasks.length,
|
|
4476
|
+
assignee_email,
|
|
4439
4477
|
tasks: result.tasks,
|
|
4440
4478
|
}, null, 2),
|
|
4441
4479
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fruition/fcp-mcp-server",
|
|
3
|
-
"version": "1.27.
|
|
3
|
+
"version": "1.27.1",
|
|
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",
|