@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.
Files changed (2) hide show
  1. package/dist/index.js +42 -4
  2. 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 the current user (based on API key). Useful for finding your work items.',
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
- // Note: The API key determines the user, tasks are filtered server-side
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.0",
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",