feat(mcp-server): fill DOMAIN_PRODUCTS.md tool gaps — +17 tools across 6 products
- mindlyst: +memory.get (single item with full TriageResult) - lysnrai: +transcripts.get, +orgs.get - jarvis: +agents.create, +marketplace.listPending/certify/suspend/feature - chronomind: +timers.create, +households.list - nomgap: +protocols.list, +bodyStages.list - peakpulse: +sessions.get
This commit is contained in:
parent
c9022665d6
commit
481760fba1
@ -52,6 +52,27 @@ export interface TimerDoc {
|
||||
syncVersion: number;
|
||||
}
|
||||
|
||||
export interface TimerCreateInput {
|
||||
id: string;
|
||||
label: string;
|
||||
type: 'alarm' | 'countdown' | 'pomodoro' | 'event';
|
||||
state: 'idle' | 'active' | 'paused';
|
||||
urgency: 'critical' | 'important' | 'standard' | 'gentle' | 'passive';
|
||||
duration?: number;
|
||||
targetTime?: string;
|
||||
category?: string;
|
||||
cascade?: unknown;
|
||||
syncVersion: number;
|
||||
deviceId?: string;
|
||||
}
|
||||
|
||||
export function chronomindTimerCreate(
|
||||
input: TimerCreateInput,
|
||||
opts: ChronoMindClientOptions
|
||||
): Promise<TimerDoc> {
|
||||
return chronomindFetch('/timers', { method: 'POST', body: JSON.stringify(input) }, opts);
|
||||
}
|
||||
|
||||
export function chronomindTimersList(
|
||||
params: { limit?: number; offset?: number; type?: string; state?: string },
|
||||
opts: ChronoMindClientOptions
|
||||
@ -108,6 +129,19 @@ export function chronomindRoutinesList(
|
||||
return chronomindFetch(`/routines${q ? `?${q}` : ''}`, { method: 'GET' }, opts);
|
||||
}
|
||||
|
||||
// ── Households ────────────────────────────────────────────────────────────
|
||||
|
||||
export function chronomindHouseholdsList(
|
||||
params: { limit?: number; offset?: number },
|
||||
opts: ChronoMindClientOptions
|
||||
): Promise<{ items: unknown[]; total: number }> {
|
||||
const qs = new URLSearchParams();
|
||||
if (params.limit !== undefined) qs.set('limit', String(params.limit));
|
||||
if (params.offset !== undefined) qs.set('offset', String(params.offset));
|
||||
const q = qs.toString();
|
||||
return chronomindFetch(`/households${q ? `?${q}` : ''}`, { method: 'GET' }, opts);
|
||||
}
|
||||
|
||||
export function chronomindTimerDelete(
|
||||
timerId: string,
|
||||
opts: ChronoMindClientOptions
|
||||
|
||||
@ -61,6 +61,27 @@ export interface JarvisAgentDoc {
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface AgentCreateInput {
|
||||
name: string;
|
||||
role: string;
|
||||
systemPrompt: string;
|
||||
voiceId?: string;
|
||||
coachingFramework?: string;
|
||||
accentColor?: string;
|
||||
welcomeMessage?: string;
|
||||
sessionLength?: number;
|
||||
difficultyLevel?: 'beginner' | 'intermediate' | 'advanced';
|
||||
language?: string;
|
||||
privacyLevel?: 'standard' | 'strict';
|
||||
}
|
||||
|
||||
export function jarvisAgentCreate(
|
||||
input: AgentCreateInput,
|
||||
opts: JarvisClientOptions
|
||||
): Promise<JarvisAgentDoc> {
|
||||
return jarvisFetch('/jarvis/agents', { method: 'POST', body: JSON.stringify(input) }, opts);
|
||||
}
|
||||
|
||||
export function jarvisAgentsList(
|
||||
params: { limit?: number; offset?: number },
|
||||
opts: JarvisClientOptions
|
||||
@ -160,6 +181,50 @@ export function jarvisMemoryList(
|
||||
);
|
||||
}
|
||||
|
||||
// ── Marketplace admin ─────────────────────────────────────────────────────
|
||||
|
||||
export function jarvisMarketplaceListPending(
|
||||
opts: JarvisClientOptions
|
||||
): Promise<{ listings: unknown[]; total: number }> {
|
||||
return jarvisFetch('/marketplace/admin/pending', { method: 'GET' }, opts);
|
||||
}
|
||||
|
||||
export function jarvisMarketplaceCertify(
|
||||
listingId: string,
|
||||
decision: { decision: 'approved' | 'rejected'; notes?: string },
|
||||
opts: JarvisClientOptions
|
||||
): Promise<unknown> {
|
||||
return jarvisFetch(
|
||||
`/marketplace/admin/${listingId}/approve`,
|
||||
{ method: 'POST', body: JSON.stringify(decision) },
|
||||
opts
|
||||
);
|
||||
}
|
||||
|
||||
export function jarvisMarketplaceSuspend(
|
||||
listingId: string,
|
||||
reason: string,
|
||||
opts: JarvisClientOptions
|
||||
): Promise<unknown> {
|
||||
return jarvisFetch(
|
||||
`/marketplace/admin/${listingId}/suspend`,
|
||||
{ method: 'POST', body: JSON.stringify({ reason }) },
|
||||
opts
|
||||
);
|
||||
}
|
||||
|
||||
export function jarvisMarketplaceFeature(
|
||||
listingId: string,
|
||||
featured: boolean,
|
||||
opts: JarvisClientOptions
|
||||
): Promise<unknown> {
|
||||
return jarvisFetch(
|
||||
`/marketplace/admin/${listingId}/feature`,
|
||||
{ method: 'POST', body: JSON.stringify({ featured }) },
|
||||
opts
|
||||
);
|
||||
}
|
||||
|
||||
export function jarvisMemoryPrune(
|
||||
agentId: string,
|
||||
opts: JarvisClientOptions
|
||||
|
||||
@ -66,6 +66,13 @@ export function lysnraiTranscriptsList(
|
||||
return lysnraiFetch(`/transcripts${q ? `?${q}` : ''}`, { method: 'GET' }, opts);
|
||||
}
|
||||
|
||||
export function lysnraiTranscriptGet(
|
||||
id: string,
|
||||
opts: LysnraiClientOptions
|
||||
): Promise<TranscriptDoc> {
|
||||
return lysnraiFetch(`/transcripts/${id}`, { method: 'GET' }, opts);
|
||||
}
|
||||
|
||||
export function lysnraiTranscriptRunExtraction(
|
||||
transcriptId: string,
|
||||
opts: LysnraiClientOptions
|
||||
@ -126,6 +133,10 @@ export interface OrgDoc {
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export function lysnraiOrgGet(orgId: string, opts: LysnraiClientOptions): Promise<OrgDoc> {
|
||||
return lysnraiFetch(`/orgs/${orgId}`, { method: 'GET' }, opts);
|
||||
}
|
||||
|
||||
export function lysnraiOrgsList(
|
||||
params: { limit?: number; offset?: number },
|
||||
opts: LysnraiClientOptions
|
||||
|
||||
@ -88,6 +88,13 @@ export function mindlystMemoryList(
|
||||
return mindlystFetch(`/memory-items${q ? `?${q}` : ''}`, { method: 'GET' }, opts);
|
||||
}
|
||||
|
||||
export function mindlystMemoryGetItem(
|
||||
itemId: string,
|
||||
opts: MindlystClientOptions
|
||||
): Promise<MemoryItemDoc> {
|
||||
return mindlystFetch(`/memory-items/${itemId}`, { method: 'GET' }, opts);
|
||||
}
|
||||
|
||||
export function mindlystMemoryRetriage(
|
||||
itemId: string,
|
||||
opts: MindlystClientOptions
|
||||
|
||||
@ -85,6 +85,22 @@ export function nomgapFastingGetWeeklyStats(
|
||||
return nomgapFetch('/fasting/stats/weekly', { method: 'GET' }, opts);
|
||||
}
|
||||
|
||||
// ── Protocols ─────────────────────────────────────────────────────────────
|
||||
|
||||
export function nomgapProtocolsList(
|
||||
opts: NomGapClientOptions
|
||||
): Promise<{ protocols: unknown[]; total: number }> {
|
||||
return nomgapFetch('/fasting/protocols', { method: 'GET' }, opts);
|
||||
}
|
||||
|
||||
// ── Body stages (public — no auth required) ────────────────────────────────
|
||||
|
||||
export function nomgapBodyStagesList(
|
||||
opts: Pick<NomGapClientOptions, 'requestId'>
|
||||
): Promise<{ stages: unknown[]; total: number }> {
|
||||
return nomgapFetch('/fasting/stages', { method: 'GET' }, opts);
|
||||
}
|
||||
|
||||
// ── Push triggers ──────────────────────────────────────────────────────────
|
||||
|
||||
export type PushTriggerType =
|
||||
|
||||
@ -105,6 +105,13 @@ export function peakpulseSessionsList(
|
||||
return peakpulseFetch(`/peak/sessions${q ? `?${q}` : ''}`, { method: 'GET' }, opts);
|
||||
}
|
||||
|
||||
export function peakpulseSessionGet(
|
||||
sessionId: string,
|
||||
opts: PeakPulseClientOptions
|
||||
): Promise<PeakSessionDoc> {
|
||||
return peakpulseFetch(`/peak/sessions/${sessionId}`, { method: 'GET' }, opts);
|
||||
}
|
||||
|
||||
export function peakpulseSessionExport(
|
||||
sessionId: string,
|
||||
opts: PeakPulseClientOptions
|
||||
|
||||
@ -9,15 +9,43 @@ import { z } from 'zod';
|
||||
import { registerTool } from '../tools/registry.js';
|
||||
import { config } from '../../lib/config.js';
|
||||
import {
|
||||
chronomindTimerCreate,
|
||||
chronomindTimersList,
|
||||
chronomindTimerDelete,
|
||||
chronomindRoutinesList,
|
||||
chronomindSyncStatus,
|
||||
chronomindHouseholdsList,
|
||||
} from '../../lib/chronomind-client.js';
|
||||
import type { McpToolRequest } from '../tools/types.js';
|
||||
|
||||
const tokenOf = (req: McpToolRequest) => req.headers.authorization?.slice(7);
|
||||
|
||||
// ── chronomind.timers.create ───────────────────────────────────────────────
|
||||
|
||||
registerTool({
|
||||
name: 'chronomind.timers.create',
|
||||
description:
|
||||
'Create a new cloud-synced timer. The id and syncVersion must be provided by the caller (client-generated UUID and current version). Requires admin role.',
|
||||
requiredRole: 'admin',
|
||||
inputSchema: z.object({
|
||||
id: z.string().min(1).describe('Client-generated timer UUID'),
|
||||
label: z.string().min(1).describe('Timer display name'),
|
||||
type: z.enum(['alarm', 'countdown', 'pomodoro', 'event']),
|
||||
urgency: z.enum(['critical', 'important', 'standard', 'gentle', 'passive']).default('standard'),
|
||||
duration: z.coerce.number().optional().describe('Duration in seconds (countdown/pomodoro)'),
|
||||
targetTime: z.string().optional().describe('ISO 8601 target time (alarm/event)'),
|
||||
category: z.string().optional().describe('Timer category label'),
|
||||
syncVersion: z.coerce.number().default(1),
|
||||
deviceId: z.string().optional().describe('Origin device ID for conflict detection'),
|
||||
}),
|
||||
async execute(args, req) {
|
||||
return chronomindTimerCreate(
|
||||
{ ...args, state: 'idle' },
|
||||
{ token: tokenOf(req), requestId: req.id }
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
// ── chronomind.timers.list ────────────────────────────────────────────────
|
||||
|
||||
registerTool({
|
||||
@ -88,3 +116,19 @@ registerTool({
|
||||
return chronomindSyncStatus({ token: tokenOf(req), requestId: req.id });
|
||||
},
|
||||
});
|
||||
|
||||
// ── chronomind.households.list ────────────────────────────────────────────
|
||||
|
||||
registerTool({
|
||||
name: 'chronomind.households.list',
|
||||
description:
|
||||
'List ChronoMind Family-tier households the authenticated user belongs to, including member list and invite codes. Requires admin role.',
|
||||
requiredRole: 'admin',
|
||||
inputSchema: z.object({
|
||||
limit: z.coerce.number().min(1).max(config.QUERY_MAX_LIMIT).default(config.QUERY_DEFAULT_LIMIT),
|
||||
offset: z.coerce.number().min(0).default(0),
|
||||
}),
|
||||
async execute(args, req) {
|
||||
return chronomindHouseholdsList(args, { token: tokenOf(req), requestId: req.id });
|
||||
},
|
||||
});
|
||||
|
||||
@ -9,6 +9,7 @@ import { z } from 'zod';
|
||||
import { registerTool } from '../tools/registry.js';
|
||||
import { config } from '../../lib/config.js';
|
||||
import {
|
||||
jarvisAgentCreate,
|
||||
jarvisAgentsList,
|
||||
jarvisAgentDuplicate,
|
||||
jarvisSessionsList,
|
||||
@ -16,11 +17,40 @@ import {
|
||||
jarvisMemoryList,
|
||||
jarvisMemoryPrune,
|
||||
jarvisMemoryGetContext,
|
||||
jarvisMarketplaceListPending,
|
||||
jarvisMarketplaceCertify,
|
||||
jarvisMarketplaceSuspend,
|
||||
jarvisMarketplaceFeature,
|
||||
} from '../../lib/jarvis-client.js';
|
||||
import type { McpToolRequest } from '../tools/types.js';
|
||||
|
||||
const tokenOf = (req: McpToolRequest) => req.headers.authorization?.slice(7);
|
||||
|
||||
// ── jarvis.agents.create ─────────────────────────────────────────────────
|
||||
|
||||
registerTool({
|
||||
name: 'jarvis.agents.create',
|
||||
description:
|
||||
'Create a new coaching agent with a system prompt, role, and coaching framework. Returns the created agent including its ID. Requires admin role.',
|
||||
requiredRole: 'admin',
|
||||
inputSchema: z.object({
|
||||
name: z.string().min(1).describe('Agent display name'),
|
||||
role: z.string().min(1).describe('Agent role (e.g. Career Coach, Language Tutor)'),
|
||||
systemPrompt: z.string().min(1).describe('System prompt for the agent'),
|
||||
coachingFramework: z.string().optional().describe('Coaching methodology (e.g. GROW, CBT)'),
|
||||
voiceId: z.string().optional().describe('TTS voice identifier'),
|
||||
difficultyLevel: z
|
||||
.enum(['beginner', 'intermediate', 'advanced'])
|
||||
.optional()
|
||||
.default('intermediate'),
|
||||
language: z.string().optional().default('en'),
|
||||
privacyLevel: z.enum(['standard', 'strict']).optional().default('standard'),
|
||||
}),
|
||||
async execute(args, req) {
|
||||
return jarvisAgentCreate(args, { token: tokenOf(req), requestId: req.id });
|
||||
},
|
||||
});
|
||||
|
||||
// ── jarvis.agents.list ────────────────────────────────────────────────────
|
||||
|
||||
registerTool({
|
||||
@ -148,3 +178,75 @@ registerTool({
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
// ── jarvis.marketplace.listPending ───────────────────────────────────────
|
||||
|
||||
registerTool({
|
||||
name: 'jarvis.marketplace.listPending',
|
||||
description:
|
||||
'List marketplace listings awaiting certification (status = pending_review). For admin use in the certification pipeline. Requires admin role.',
|
||||
requiredRole: 'admin',
|
||||
inputSchema: z.object({}),
|
||||
async execute(_args, req) {
|
||||
return jarvisMarketplaceListPending({ token: tokenOf(req), requestId: req.id });
|
||||
},
|
||||
});
|
||||
|
||||
// ── jarvis.marketplace.certify ───────────────────────────────────────────
|
||||
|
||||
registerTool({
|
||||
name: 'jarvis.marketplace.certify',
|
||||
description:
|
||||
'Approve or reject a marketplace listing. Sets isVerified flag and notifies the author. Requires admin role.',
|
||||
requiredRole: 'admin',
|
||||
inputSchema: z.object({
|
||||
listingId: z.string().min(1).describe('Listing ID'),
|
||||
decision: z.enum(['approved', 'rejected']).describe('Certification decision'),
|
||||
notes: z.string().optional().describe('Optional review notes for the author'),
|
||||
}),
|
||||
async execute(args, req) {
|
||||
const { listingId, ...decision } = args;
|
||||
return jarvisMarketplaceCertify(listingId, decision, {
|
||||
token: tokenOf(req),
|
||||
requestId: req.id,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
// ── jarvis.marketplace.suspend ───────────────────────────────────────────
|
||||
|
||||
registerTool({
|
||||
name: 'jarvis.marketplace.suspend',
|
||||
description:
|
||||
'Suspend a published marketplace listing (e.g. policy violation). Requires admin role.',
|
||||
requiredRole: 'admin',
|
||||
inputSchema: z.object({
|
||||
listingId: z.string().min(1).describe('Listing ID to suspend'),
|
||||
reason: z.string().min(1).describe('Suspension reason shown to the author'),
|
||||
}),
|
||||
async execute(args, req) {
|
||||
return jarvisMarketplaceSuspend(args.listingId, args.reason, {
|
||||
token: tokenOf(req),
|
||||
requestId: req.id,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
// ── jarvis.marketplace.feature ───────────────────────────────────────────
|
||||
|
||||
registerTool({
|
||||
name: 'jarvis.marketplace.feature',
|
||||
description:
|
||||
'Toggle featured status on a marketplace listing (shows on homepage hero carousel). Requires admin role.',
|
||||
requiredRole: 'admin',
|
||||
inputSchema: z.object({
|
||||
listingId: z.string().min(1).describe('Listing ID'),
|
||||
featured: z.boolean().describe('true = feature, false = unfeature'),
|
||||
}),
|
||||
async execute(args, req) {
|
||||
return jarvisMarketplaceFeature(args.listingId, args.featured, {
|
||||
token: tokenOf(req),
|
||||
requestId: req.id,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
@ -11,16 +11,33 @@ import { registerTool } from '../tools/registry.js';
|
||||
import { config } from '../../lib/config.js';
|
||||
import {
|
||||
lysnraiTranscriptsList,
|
||||
lysnraiTranscriptGet,
|
||||
lysnraiTranscriptRunExtraction,
|
||||
lysnraiSttGetBackendStatus,
|
||||
lysnraiSessionsList,
|
||||
lysnraiOrgsList,
|
||||
lysnraiOrgGet,
|
||||
lysnraiApiTokensList,
|
||||
} from '../../lib/lysnrai-client.js';
|
||||
import type { McpToolRequest } from '../tools/types.js';
|
||||
|
||||
const tokenOf = (req: McpToolRequest) => req.headers.authorization?.slice(7);
|
||||
|
||||
// ── lysnrai.transcripts.get ───────────────────────────────────────────────
|
||||
|
||||
registerTool({
|
||||
name: 'lysnrai.transcripts.get',
|
||||
description:
|
||||
'Get a single transcript by ID, including extractions[] and extractionMetadata if extraction has run. Requires admin role.',
|
||||
requiredRole: 'admin',
|
||||
inputSchema: z.object({
|
||||
transcriptId: z.string().min(1).describe('Transcript ID'),
|
||||
}),
|
||||
async execute(args, req) {
|
||||
return lysnraiTranscriptGet(args.transcriptId, { token: tokenOf(req), requestId: req.id });
|
||||
},
|
||||
});
|
||||
|
||||
// ── lysnrai.transcripts.list ──────────────────────────────────────────────
|
||||
|
||||
registerTool({
|
||||
@ -101,6 +118,21 @@ registerTool({
|
||||
},
|
||||
});
|
||||
|
||||
// ── lysnrai.orgs.get ─────────────────────────────────────────────────────
|
||||
|
||||
registerTool({
|
||||
name: 'lysnrai.orgs.get',
|
||||
description:
|
||||
'Get a single organisation by ID including member count, vocabulary, and shared instructions. Requires admin role.',
|
||||
requiredRole: 'admin',
|
||||
inputSchema: z.object({
|
||||
orgId: z.string().min(1).describe('Organisation ID'),
|
||||
}),
|
||||
async execute(args, req) {
|
||||
return lysnraiOrgGet(args.orgId, { token: tokenOf(req), requestId: req.id });
|
||||
},
|
||||
});
|
||||
|
||||
// ── lysnrai.apiTokens.list ────────────────────────────────────────────────
|
||||
|
||||
registerTool({
|
||||
|
||||
@ -11,6 +11,7 @@ import { registerTool } from '../tools/registry.js';
|
||||
import { config } from '../../lib/config.js';
|
||||
import {
|
||||
mindlystMemoryList,
|
||||
mindlystMemoryGetItem,
|
||||
mindlystMemoryRetriage,
|
||||
mindlystMemoryPatch,
|
||||
mindlystMemoryReassign,
|
||||
@ -25,6 +26,21 @@ import type { McpToolRequest } from '../tools/types.js';
|
||||
|
||||
const tokenOf = (req: McpToolRequest) => req.headers.authorization?.slice(7);
|
||||
|
||||
// ── mindlyst.memory.get ───────────────────────────────────────────────────
|
||||
|
||||
registerTool({
|
||||
name: 'mindlyst.memory.get',
|
||||
description:
|
||||
'Get a single memory item by ID, including its full TriageResult (urgencyScore, emotionScore, confidenceScore, entities, suggestedActions). Requires admin role.',
|
||||
requiredRole: 'admin',
|
||||
inputSchema: z.object({
|
||||
itemId: z.string().min(1).describe('Memory item ID'),
|
||||
}),
|
||||
async execute(args, req) {
|
||||
return mindlystMemoryGetItem(args.itemId, { token: tokenOf(req), requestId: req.id });
|
||||
},
|
||||
});
|
||||
|
||||
// ── mindlyst.memory.list ──────────────────────────────────────────────────
|
||||
|
||||
registerTool({
|
||||
|
||||
@ -12,6 +12,8 @@ import {
|
||||
nomgapFastingSessionsList,
|
||||
nomgapFastingGetStats,
|
||||
nomgapFastingGetWeeklyStats,
|
||||
nomgapProtocolsList,
|
||||
nomgapBodyStagesList,
|
||||
nomgapPushFire,
|
||||
nomgapPushGetStats,
|
||||
nomgapPushGetPending,
|
||||
@ -130,6 +132,32 @@ registerTool({
|
||||
},
|
||||
});
|
||||
|
||||
// ── nomgap.protocols.list ──────────────────────────────────────────────────
|
||||
|
||||
registerTool({
|
||||
name: 'nomgap.protocols.list',
|
||||
description:
|
||||
'List all fasting protocols (built-in + user custom). Includes fastHours, eatHours, difficulty, and type. Requires admin role.',
|
||||
requiredRole: 'admin',
|
||||
inputSchema: z.object({}),
|
||||
async execute(_args, req) {
|
||||
return nomgapProtocolsList({ token: tokenOf(req), requestId: req.id });
|
||||
},
|
||||
});
|
||||
|
||||
// ── nomgap.bodyStages.list ───────────────────────────────────────────────
|
||||
|
||||
registerTool({
|
||||
name: 'nomgap.bodyStages.list',
|
||||
description:
|
||||
'List all 6 fasting body stages (fed, early_fast, fasted, ketosis, deep_autophagy, extended) with hour thresholds and visualization metadata. Public endpoint — no auth needed.',
|
||||
requiredRole: 'admin',
|
||||
inputSchema: z.object({}),
|
||||
async execute(_args, req) {
|
||||
return nomgapBodyStagesList({ requestId: req.id });
|
||||
},
|
||||
});
|
||||
|
||||
// ── nomgap.push.pending ───────────────────────────────────────────────────
|
||||
|
||||
registerTool({
|
||||
|
||||
@ -10,6 +10,7 @@ import { registerTool } from '../tools/registry.js';
|
||||
import { config } from '../../lib/config.js';
|
||||
import {
|
||||
peakpulseSessionsList,
|
||||
peakpulseSessionGet,
|
||||
peakpulseSessionExport,
|
||||
peakpulseGetStats,
|
||||
peakpulseRouteGet,
|
||||
@ -70,7 +71,22 @@ registerTool({
|
||||
},
|
||||
});
|
||||
|
||||
// ── peakpulse.routes.get ──────────────────────────────────────────────────
|
||||
// ── peakpulse.sessions.get ──────────────────────────────────────────────────
|
||||
|
||||
registerTool({
|
||||
name: 'peakpulse.sessions.get',
|
||||
description:
|
||||
'Get a single adventure session by ID including activityType, GPS trackPoints summary, ski/hike metrics, weather snapshot, and haptic events. Requires admin role.',
|
||||
requiredRole: 'admin',
|
||||
inputSchema: z.object({
|
||||
sessionId: z.string().min(1).describe('Session ID'),
|
||||
}),
|
||||
async execute(args, req) {
|
||||
return peakpulseSessionGet(args.sessionId, { token: tokenOf(req), requestId: req.id });
|
||||
},
|
||||
});
|
||||
|
||||
// ── peakpulse.routes.get ────────────────────────────────────────────────────
|
||||
|
||||
registerTool({
|
||||
name: 'peakpulse.routes.get',
|
||||
|
||||
Loading…
Reference in New Issue
Block a user