agent-ecosystem/mcp-server/src/tools/task-attach.ts
iliya 161c675aaa feat: update pnpm lockfile and workspace configuration, enhance tool usage tracking and UI components
- Added new dependencies for mcp-server in pnpm-lock.yaml, including fastmcp and zod.
- Updated pnpm-workspace.yaml to include mcp-server in the workspace packages.
- Modified TeamDataService and TeamProvisioningService to exclude 'SendMessage' from tool usage counts, improving accuracy in tool tracking.
- Enhanced ChatHistory component to display context injection percentages, improving user feedback on context usage.
- Updated TeamDetailView to ensure session details are fetched periodically for active tabs, enhancing data freshness.
- Improved ActivityTimeline styling for better visual separation of sessions and messages.
2026-03-06 15:54:55 +02:00

42 lines
1.9 KiB
TypeScript

import { z } from 'zod';
import { UserError } from 'fastmcp';
import type { FastMCP } from 'fastmcp';
import type { ITeamctlRunner } from '../teamctl-runner.js';
import { parseJsonOutput } from '../output-parser.js';
import { teamNameSchema, taskIdSchema, memberNameSchema, filePathSchema, safeFilenameSchema, mimeTypeSchema } from '../schemas.js';
export function register(server: FastMCP, runner: ITeamctlRunner): void {
server.addTool({
name: 'task_attach',
description: `Attach a file to a task. Returns attachment metadata JSON.
Supports copy (default) or hardlink mode. MIME type is auto-detected from file content (PNG, JPEG, GIF, WebP, PDF, ZIP) with fallback to application/octet-stream. Max file size: 20 MB.`,
annotations: {
readOnlyHint: false,
destructiveHint: false,
},
parameters: z.object({
team: teamNameSchema,
task_id: taskIdSchema,
file: filePathSchema.describe('Absolute path to the file to attach'),
filename: safeFilenameSchema.optional().describe('Override stored filename'),
mime_type: mimeTypeSchema.optional().describe('Override MIME type (auto-detected by default)'),
mode: z.enum(['copy', 'link']).optional().describe('Storage mode: copy (default) or hardlink'),
from: memberNameSchema.optional().describe('Uploader name'),
}),
execute: async (args) => {
const cliArgs = ['--team', args.team, 'task', 'attach', args.task_id, '--file', args.file];
if (args.filename) cliArgs.push('--filename', args.filename);
if (args.mime_type) cliArgs.push('--mime-type', args.mime_type);
if (args.mode) cliArgs.push('--mode', args.mode);
if (args.from) cliArgs.push('--from', args.from);
const result = await runner.execute(cliArgs);
if (result.exitCode !== 0) {
throw new UserError(`Failed to attach file: ${result.stderr.trim() || result.stdout.trim()}`);
}
return parseJsonOutput(result.stdout);
},
});
}