Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -625,6 +625,7 @@ Configure via `skillsConfig.auth` option:
❌ **Don't**: Name event properties `scope` when they don't refer to Scope class
❌ **Don't**: Put auth-related code in libs/sdk/src/auth (use libs/auth instead)
❌ **Don't**: Name test files with `.test.ts` extension (use `.spec.ts` instead)
❌ **Don't**: Use `ToolContext<typeof inputSchema>` — types are auto-inferred from the `@Tool` decorator; use plain `ToolContext`

✅ **Do**: Use clean, descriptive names for everything
✅ **Do**: Use `@frontmcp/utils` for file system and crypto operations
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Tool, ToolContext } from '@frontmcp/sdk';
import { z } from 'zod';

import { Tool, ToolContext } from '@frontmcp/sdk';

const inputSchema = { action: z.string().default('admin-action') };
type Input = z.infer<z.ZodObject<typeof inputSchema>>;

Expand All @@ -12,7 +13,7 @@ type Input = z.infer<z.ZodObject<typeof inputSchema>>;
roles: { any: ['admin', 'superadmin'] },
},
})
export default class AdminOnlyTool extends ToolContext<typeof inputSchema> {
export default class AdminOnlyTool extends ToolContext {
async execute(input: Input) {
return { result: `admin action: ${input.action}` };
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Tool, ToolContext } from '@frontmcp/sdk';
import { z } from 'zod';

import { Tool, ToolContext } from '@frontmcp/sdk';

const inputSchema = { action: z.string().default('combined') };
type Input = z.infer<z.ZodObject<typeof inputSchema>>;

Expand All @@ -12,15 +13,12 @@ type Input = z.infer<z.ZodObject<typeof inputSchema>>;
anyOf: [
{ roles: { any: ['superadmin'] } },
{
allOf: [
{ roles: { any: ['admin', 'manager'] } },
{ not: { roles: { any: ['suspended'] } } },
],
allOf: [{ roles: { any: ['admin', 'manager'] } }, { not: { roles: { any: ['suspended'] } } }],
},
],
},
})
export default class CombinatorTool extends ToolContext<typeof inputSchema> {
export default class CombinatorTool extends ToolContext {
async execute(input: Input) {
return { result: input.action };
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Tool, ToolContext } from '@frontmcp/sdk';
import { z } from 'zod';

import { Tool, ToolContext } from '@frontmcp/sdk';

const inputSchema = { content: z.string().default('draft') };
type Input = z.infer<z.ZodObject<typeof inputSchema>>;

Expand All @@ -9,13 +10,10 @@ type Input = z.infer<z.ZodObject<typeof inputSchema>>;
description: 'A tool accessible to editors OR admins (anyOf combinator)',
inputSchema,
authorities: {
anyOf: [
{ roles: { any: ['admin'] } },
{ permissions: { any: ['content:write', 'content:publish'] } },
],
anyOf: [{ roles: { any: ['admin'] } }, { permissions: { any: ['content:write', 'content:publish'] } }],
},
})
export default class EditorOrAdminTool extends ToolContext<typeof inputSchema> {
export default class EditorOrAdminTool extends ToolContext {
async execute(input: Input) {
return { published: input.content };
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Tool, ToolContext } from '@frontmcp/sdk';
import { z } from 'zod';

import { Tool, ToolContext } from '@frontmcp/sdk';

const inputSchema = { resource: z.string().default('users') };
type Input = z.infer<z.ZodObject<typeof inputSchema>>;

Expand All @@ -12,7 +13,7 @@ type Input = z.infer<z.ZodObject<typeof inputSchema>>;
permissions: { all: ['users:read', 'users:write'] },
},
})
export default class PermissionsTool extends ToolContext<typeof inputSchema> {
export default class PermissionsTool extends ToolContext {
async execute(input: Input) {
return { access: 'granted', resource: input.resource };
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Tool, ToolContext } from '@frontmcp/sdk';
import { z } from 'zod';

import { Tool, ToolContext } from '@frontmcp/sdk';

const inputSchema = { query: z.string().default('status') };
type Input = z.infer<z.ZodObject<typeof inputSchema>>;

Expand All @@ -10,7 +11,7 @@ type Input = z.infer<z.ZodObject<typeof inputSchema>>;
inputSchema,
authorities: 'admin',
})
export default class ProfileAdminTool extends ToolContext<typeof inputSchema> {
export default class ProfileAdminTool extends ToolContext {
async execute(input: Input) {
return { admin: true, query: input.query };
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Tool, ToolContext } from '@frontmcp/sdk';
import { z } from 'zod';

import { Tool, ToolContext } from '@frontmcp/sdk';

const inputSchema = {
tenantId: z.string(),
value: z.string().default('data'),
Expand All @@ -13,7 +14,7 @@ type Input = z.infer<z.ZodObject<typeof inputSchema>>;
inputSchema,
authorities: ['authenticated', 'matchTenant'],
})
export default class ProfileMultiTool extends ToolContext<typeof inputSchema> {
export default class ProfileMultiTool extends ToolContext {
async execute(input: Input) {
return { tenant: input.tenantId, value: input.value };
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Tool, ToolContext } from '@frontmcp/sdk';
import { z } from 'zod';

import { Tool, ToolContext } from '@frontmcp/sdk';

const inputSchema = { message: z.string().default('hello') };
type Input = z.infer<z.ZodObject<typeof inputSchema>>;

Expand All @@ -9,7 +10,7 @@ type Input = z.infer<z.ZodObject<typeof inputSchema>>;
description: 'A tool with no authorities — accessible to everyone',
inputSchema,
})
export default class PublicTool extends ToolContext<typeof inputSchema> {
export default class PublicTool extends ToolContext {
async execute(input: Input) {
return { echo: input.message };
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Tool, ToolContext } from '@frontmcp/sdk';
import { z } from 'zod';

import { Tool, ToolContext } from '@frontmcp/sdk';

const inputSchema = {
tenantId: z.string(),
data: z.string().default('payload'),
Expand All @@ -13,13 +14,11 @@ type Input = z.infer<z.ZodObject<typeof inputSchema>>;
inputSchema,
authorities: {
attributes: {
conditions: [
{ path: 'claims.tenantId', op: 'eq', value: { fromInput: 'tenantId' } },
],
conditions: [{ path: 'claims.tenantId', op: 'eq', value: { fromInput: 'tenantId' } }],
},
},
})
export default class TenantScopedTool extends ToolContext<typeof inputSchema> {
export default class TenantScopedTool extends ToolContext {
async execute(input: Input) {
return { tenant: input.tenantId, data: input.data };
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { Tool, ToolContext } from '@frontmcp/sdk';
import { z } from 'zod';

import { Tool, ToolContext } from '@frontmcp/sdk';

import { executionTracker } from '../data/execution-tracker';

const inputSchema = {
Expand All @@ -26,7 +28,7 @@ type Output = z.infer<typeof outputSchema>;
ttl: 30, // 30 second TTL
},
})
export default class ExpensiveOperationTool extends ToolContext<typeof inputSchema, typeof outputSchema> {
export default class ExpensiveOperationTool extends ToolContext {
async execute(input: Input): Promise<Output> {
// Track actual execution
const executionCount = executionTracker.increment('expensive-operation');
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { Tool, ToolContext } from '@frontmcp/sdk';
import { z } from 'zod';

import { Tool, ToolContext } from '@frontmcp/sdk';

import { executionTracker } from '../data/execution-tracker';

const inputSchema = {};
Expand All @@ -18,7 +20,7 @@ type Output = z.infer<typeof outputSchema>;
inputSchema,
outputSchema,
})
export default class GetCacheStatsTool extends ToolContext<typeof inputSchema, typeof outputSchema> {
export default class GetCacheStatsTool extends ToolContext {
async execute(_input: Input): Promise<Output> {
const counts = executionTracker.getAll();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { Tool, ToolContext } from '@frontmcp/sdk';
import { z } from 'zod';

import { Tool, ToolContext } from '@frontmcp/sdk';

import { executionTracker } from '../data/execution-tracker';

const inputSchema = {
Expand All @@ -23,7 +25,7 @@ type Output = z.infer<typeof outputSchema>;
outputSchema,
// No cache configuration - every call executes
})
export default class NonCachedTool extends ToolContext<typeof inputSchema, typeof outputSchema> {
export default class NonCachedTool extends ToolContext {
async execute(input: Input): Promise<Output> {
// Track actual execution
const executionCount = executionTracker.increment('non-cached');
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { Tool, ToolContext } from '@frontmcp/sdk';
import { z } from 'zod';

import { Tool, ToolContext } from '@frontmcp/sdk';

import { executionTracker } from '../data/execution-tracker';

const inputSchema = {};
Expand All @@ -18,7 +20,7 @@ type Output = z.infer<typeof outputSchema>;
inputSchema,
outputSchema,
})
export default class ResetStatsTool extends ToolContext<typeof inputSchema, typeof outputSchema> {
export default class ResetStatsTool extends ToolContext {
async execute(_input: Input): Promise<Output> {
executionTracker.reset();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@
* 2. Recipient replies → onEvent() triggered → notification to Claude
*/

import { Channel, ChannelContext, Tool, ToolContext } from '@frontmcp/sdk';
import type { ChannelNotification } from '@frontmcp/sdk';
import { z } from 'zod';

import { Channel, ChannelContext, Tool, ToolContext, type ChannelNotification } from '@frontmcp/sdk';

// ─── Simulated Service State ────────────────────────────────────

/** Log of all messages sent through the service (for test verification) */
Expand Down Expand Up @@ -52,7 +52,7 @@ const sendInputSchema = {
openWorldHint: true,
},
})
export class SendMessageTool extends ToolContext<typeof sendInputSchema> {
export class SendMessageTool extends ToolContext {
async execute(input: { to: string; text: string }) {
sentMessages.push({ to: input.to, text: input.text, timestamp: Date.now() });
return {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Tool, ToolContext } from '@frontmcp/sdk';
import { z } from 'zod';

import { Tool, ToolContext } from '@frontmcp/sdk';

const inputSchema = {
event: z.string().describe('Event name to emit (e.g., "app:error")'),
payload: z.record(z.string(), z.unknown()).describe('Event payload'),
Expand All @@ -11,7 +12,7 @@ const inputSchema = {
description: 'Emit an app event to the ChannelEventBus for testing channel sources',
inputSchema,
})
export default class EmitAppEventTool extends ToolContext<typeof inputSchema> {
export default class EmitAppEventTool extends ToolContext {
async execute(input: { event: string; payload: Record<string, unknown> }) {
const scope = this.scope as unknown as { channelEventBus?: { emit: (event: string, payload: unknown) => void } };
const eventBus = scope.channelEventBus;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { Tool, ToolContext } from '@frontmcp/sdk';
import { z } from 'zod';

import { Tool, ToolContext } from '@frontmcp/sdk';

import { simulateFileEvent } from '../channels/file-watcher.channel';

const inputSchema = {
Expand All @@ -13,7 +15,7 @@ const inputSchema = {
description: 'Simulate a file system event for the file-watcher channel',
inputSchema,
})
export default class SimulateFileEventTool extends ToolContext<typeof inputSchema> {
export default class SimulateFileEventTool extends ToolContext {
async execute(input: { file: string; event: string; content?: string }) {
simulateFileEvent(input.file, input.event, input.content);
return { simulated: true, file: input.file, event: input.event };
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Tool, ToolContext } from '@frontmcp/sdk';
import { z } from 'zod';
import type { ChannelRegistry } from '@frontmcp/sdk';

import { Tool, ToolContext, type ChannelRegistry } from '@frontmcp/sdk';

const getBufferSchema = {
channelName: z.string().describe('Channel name to get buffer for'),
Expand All @@ -11,7 +11,7 @@ const getBufferSchema = {
description: 'Get the replay buffer contents for a channel',
inputSchema: getBufferSchema,
})
export class GetReplayBufferTool extends ToolContext<typeof getBufferSchema> {
export class GetReplayBufferTool extends ToolContext {
async execute(input: { channelName: string }) {
const scope = this.scope as unknown as { channels?: ChannelRegistry };
const registry = scope.channels;
Expand All @@ -38,7 +38,7 @@ const clearBufferSchema = {
description: 'Clear the replay buffer for a channel',
inputSchema: clearBufferSchema,
})
export class ClearReplayBufferTool extends ToolContext<typeof clearBufferSchema> {
export class ClearReplayBufferTool extends ToolContext {
async execute(input: { channelName: string }) {
const scope = this.scope as unknown as { channels?: ChannelRegistry };
const registry = scope.channels;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Tool, ToolContext } from '@frontmcp/sdk';
import { z } from 'zod';

import { Tool, ToolContext } from '@frontmcp/sdk';

const inputSchema = {
channelName: z.string().describe('Channel name to send notification through'),
content: z.string().describe('Notification content'),
Expand All @@ -12,7 +13,7 @@ const inputSchema = {
description: 'Manually send a notification through the channel system',
inputSchema,
})
export default class SendChannelNotificationTool extends ToolContext<typeof inputSchema> {
export default class SendChannelNotificationTool extends ToolContext {
async execute(input: { channelName: string; content: string; meta?: Record<string, string> }) {
const scope = this.scope as unknown as {
channelNotifications?: { send: (name: string, content: string, meta?: Record<string, string>) => void };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
* sessions with the NotificationService and managing channel subscriptions.
*/

import { Tool, ToolContext } from '@frontmcp/sdk';
import { z } from 'zod';

import { Tool, ToolContext } from '@frontmcp/sdk';

// Use structural types instead of deep internal SDK imports
interface NotificationServiceLike {
registerServer(sessionId: string, server: unknown): void;
Expand Down Expand Up @@ -171,7 +173,7 @@ const manageSubSchema = {
description: 'Subscribe or unsubscribe a session from a specific channel',
inputSchema: manageSubSchema,
})
export class ManageChannelSubscriptionTool extends ToolContext<typeof manageSubSchema> {
export class ManageChannelSubscriptionTool extends ToolContext {
async execute(input: { sessionId: string; channelName: string; action: 'subscribe' | 'unsubscribe' }) {
const notifications = this.scope.notifications as NotificationServiceLike;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { Tool, ToolContext } from '@frontmcp/sdk';
import { z } from 'zod';
import { simulateIncomingMessage, sentMessages } from '../channels/messaging-service.channel';

import { Tool, ToolContext } from '@frontmcp/sdk';

import { sentMessages, simulateIncomingMessage } from '../channels/messaging-service.channel';

const inputSchema = {
from: z.string().describe('Sender name/ID'),
Expand All @@ -13,7 +15,7 @@ const inputSchema = {
description: 'Simulate an incoming message from the messaging service (for testing)',
inputSchema,
})
export default class SimulateIncomingTool extends ToolContext<typeof inputSchema> {
export default class SimulateIncomingTool extends ToolContext {
async execute(input: { from: string; text: string; chatId: string }) {
simulateIncomingMessage(input.from, input.text, input.chatId);
return { simulated: true, from: input.from };
Expand Down
Loading
Loading