@cyanheads/mcp-ts-core 0.1.0-beta.12
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/CLAUDE.md +583 -0
- package/LICENSE +201 -0
- package/README.md +287 -0
- package/biome.json +103 -0
- package/dist/app.d.ts +82 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +222 -0
- package/dist/app.js.map +1 -0
- package/dist/cli/init.d.ts +8 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +161 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/config/index.d.ts +349 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +464 -0
- package/dist/config/index.js.map +1 -0
- package/dist/context.d.ts +119 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +144 -0
- package/dist/context.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp-server/prompts/prompt-registration.d.ts +33 -0
- package/dist/mcp-server/prompts/prompt-registration.d.ts.map +1 -0
- package/dist/mcp-server/prompts/prompt-registration.js +91 -0
- package/dist/mcp-server/prompts/prompt-registration.js.map +1 -0
- package/dist/mcp-server/prompts/utils/newPromptDefinition.d.ts +49 -0
- package/dist/mcp-server/prompts/utils/newPromptDefinition.d.ts.map +1 -0
- package/dist/mcp-server/prompts/utils/newPromptDefinition.js +39 -0
- package/dist/mcp-server/prompts/utils/newPromptDefinition.js.map +1 -0
- package/dist/mcp-server/prompts/utils/promptDefinition.d.ts +37 -0
- package/dist/mcp-server/prompts/utils/promptDefinition.d.ts.map +1 -0
- package/dist/mcp-server/prompts/utils/promptDefinition.js +2 -0
- package/dist/mcp-server/prompts/utils/promptDefinition.js.map +1 -0
- package/dist/mcp-server/resources/resource-registration.d.ts +27 -0
- package/dist/mcp-server/resources/resource-registration.d.ts.map +1 -0
- package/dist/mcp-server/resources/resource-registration.js +85 -0
- package/dist/mcp-server/resources/resource-registration.js.map +1 -0
- package/dist/mcp-server/resources/utils/newResourceDefinition.d.ts +84 -0
- package/dist/mcp-server/resources/utils/newResourceDefinition.d.ts.map +1 -0
- package/dist/mcp-server/resources/utils/newResourceDefinition.js +40 -0
- package/dist/mcp-server/resources/utils/newResourceDefinition.js.map +1 -0
- package/dist/mcp-server/resources/utils/newResourceHandlerFactory.d.ts +32 -0
- package/dist/mcp-server/resources/utils/newResourceHandlerFactory.d.ts.map +1 -0
- package/dist/mcp-server/resources/utils/newResourceHandlerFactory.js +103 -0
- package/dist/mcp-server/resources/utils/newResourceHandlerFactory.js.map +1 -0
- package/dist/mcp-server/resources/utils/resourceDefinition.d.ts +94 -0
- package/dist/mcp-server/resources/utils/resourceDefinition.d.ts.map +1 -0
- package/dist/mcp-server/resources/utils/resourceDefinition.js +2 -0
- package/dist/mcp-server/resources/utils/resourceDefinition.js.map +1 -0
- package/dist/mcp-server/resources/utils/resourceHandlerFactory.d.ts +14 -0
- package/dist/mcp-server/resources/utils/resourceHandlerFactory.d.ts.map +1 -0
- package/dist/mcp-server/resources/utils/resourceHandlerFactory.js +111 -0
- package/dist/mcp-server/resources/utils/resourceHandlerFactory.js.map +1 -0
- package/dist/mcp-server/roots/roots-registration.d.ts +22 -0
- package/dist/mcp-server/roots/roots-registration.d.ts.map +1 -0
- package/dist/mcp-server/roots/roots-registration.js +25 -0
- package/dist/mcp-server/roots/roots-registration.js.map +1 -0
- package/dist/mcp-server/server.d.ts +34 -0
- package/dist/mcp-server/server.d.ts.map +1 -0
- package/dist/mcp-server/server.js +62 -0
- package/dist/mcp-server/server.js.map +1 -0
- package/dist/mcp-server/tasks/core/sessionAwareTaskStore.d.ts +42 -0
- package/dist/mcp-server/tasks/core/sessionAwareTaskStore.d.ts.map +1 -0
- package/dist/mcp-server/tasks/core/sessionAwareTaskStore.js +70 -0
- package/dist/mcp-server/tasks/core/sessionAwareTaskStore.js.map +1 -0
- package/dist/mcp-server/tasks/core/storageBackedTaskStore.d.ts +109 -0
- package/dist/mcp-server/tasks/core/storageBackedTaskStore.d.ts.map +1 -0
- package/dist/mcp-server/tasks/core/storageBackedTaskStore.js +209 -0
- package/dist/mcp-server/tasks/core/storageBackedTaskStore.js.map +1 -0
- package/dist/mcp-server/tasks/core/taskManager.d.ts +103 -0
- package/dist/mcp-server/tasks/core/taskManager.d.ts.map +1 -0
- package/dist/mcp-server/tasks/core/taskManager.js +144 -0
- package/dist/mcp-server/tasks/core/taskManager.js.map +1 -0
- package/dist/mcp-server/tasks/core/taskTypes.d.ts +11 -0
- package/dist/mcp-server/tasks/core/taskTypes.d.ts.map +1 -0
- package/dist/mcp-server/tasks/core/taskTypes.js +13 -0
- package/dist/mcp-server/tasks/core/taskTypes.js.map +1 -0
- package/dist/mcp-server/tasks/utils/taskToolDefinition.d.ts +108 -0
- package/dist/mcp-server/tasks/utils/taskToolDefinition.d.ts.map +1 -0
- package/dist/mcp-server/tasks/utils/taskToolDefinition.js +14 -0
- package/dist/mcp-server/tasks/utils/taskToolDefinition.js.map +1 -0
- package/dist/mcp-server/tools/tool-registration.d.ts +49 -0
- package/dist/mcp-server/tools/tool-registration.d.ts.map +1 -0
- package/dist/mcp-server/tools/tool-registration.js +269 -0
- package/dist/mcp-server/tools/tool-registration.js.map +1 -0
- package/dist/mcp-server/tools/utils/newToolDefinition.d.ts +73 -0
- package/dist/mcp-server/tools/utils/newToolDefinition.d.ts.map +1 -0
- package/dist/mcp-server/tools/utils/newToolDefinition.js +45 -0
- package/dist/mcp-server/tools/utils/newToolDefinition.js.map +1 -0
- package/dist/mcp-server/tools/utils/newToolHandlerFactory.d.ts +33 -0
- package/dist/mcp-server/tools/utils/newToolHandlerFactory.d.ts.map +1 -0
- package/dist/mcp-server/tools/utils/newToolHandlerFactory.js +107 -0
- package/dist/mcp-server/tools/utils/newToolHandlerFactory.js.map +1 -0
- package/dist/mcp-server/tools/utils/toolDefinition.d.ts +118 -0
- package/dist/mcp-server/tools/utils/toolDefinition.d.ts.map +1 -0
- package/dist/mcp-server/tools/utils/toolDefinition.js +2 -0
- package/dist/mcp-server/tools/utils/toolDefinition.js.map +1 -0
- package/dist/mcp-server/tools/utils/toolHandlerFactory.d.ts +34 -0
- package/dist/mcp-server/tools/utils/toolHandlerFactory.d.ts.map +1 -0
- package/dist/mcp-server/tools/utils/toolHandlerFactory.js +68 -0
- package/dist/mcp-server/tools/utils/toolHandlerFactory.js.map +1 -0
- package/dist/mcp-server/transports/ITransport.d.ts +15 -0
- package/dist/mcp-server/transports/ITransport.d.ts.map +1 -0
- package/dist/mcp-server/transports/ITransport.js +2 -0
- package/dist/mcp-server/transports/ITransport.js.map +1 -0
- package/dist/mcp-server/transports/auth/authFactory.d.ts +11 -0
- package/dist/mcp-server/transports/auth/authFactory.d.ts.map +1 -0
- package/dist/mcp-server/transports/auth/authFactory.js +43 -0
- package/dist/mcp-server/transports/auth/authFactory.js.map +1 -0
- package/dist/mcp-server/transports/auth/authMiddleware.d.ts +24 -0
- package/dist/mcp-server/transports/auth/authMiddleware.d.ts.map +1 -0
- package/dist/mcp-server/transports/auth/authMiddleware.js +69 -0
- package/dist/mcp-server/transports/auth/authMiddleware.js.map +1 -0
- package/dist/mcp-server/transports/auth/lib/authContext.d.ts +34 -0
- package/dist/mcp-server/transports/auth/lib/authContext.d.ts.map +1 -0
- package/dist/mcp-server/transports/auth/lib/authContext.js +25 -0
- package/dist/mcp-server/transports/auth/lib/authContext.js.map +1 -0
- package/dist/mcp-server/transports/auth/lib/authTypes.d.ts +19 -0
- package/dist/mcp-server/transports/auth/lib/authTypes.d.ts.map +1 -0
- package/dist/mcp-server/transports/auth/lib/authTypes.js +2 -0
- package/dist/mcp-server/transports/auth/lib/authTypes.js.map +1 -0
- package/dist/mcp-server/transports/auth/lib/authUtils.d.ts +18 -0
- package/dist/mcp-server/transports/auth/lib/authUtils.d.ts.map +1 -0
- package/dist/mcp-server/transports/auth/lib/authUtils.js +64 -0
- package/dist/mcp-server/transports/auth/lib/authUtils.js.map +1 -0
- package/dist/mcp-server/transports/auth/lib/checkScopes.d.ts +25 -0
- package/dist/mcp-server/transports/auth/lib/checkScopes.d.ts.map +1 -0
- package/dist/mcp-server/transports/auth/lib/checkScopes.js +34 -0
- package/dist/mcp-server/transports/auth/lib/checkScopes.js.map +1 -0
- package/dist/mcp-server/transports/auth/lib/claimParser.d.ts +34 -0
- package/dist/mcp-server/transports/auth/lib/claimParser.d.ts.map +1 -0
- package/dist/mcp-server/transports/auth/lib/claimParser.js +58 -0
- package/dist/mcp-server/transports/auth/lib/claimParser.js.map +1 -0
- package/dist/mcp-server/transports/auth/lib/withAuth.d.ts +25 -0
- package/dist/mcp-server/transports/auth/lib/withAuth.d.ts.map +1 -0
- package/dist/mcp-server/transports/auth/lib/withAuth.js +30 -0
- package/dist/mcp-server/transports/auth/lib/withAuth.js.map +1 -0
- package/dist/mcp-server/transports/auth/strategies/authStrategy.d.ts +18 -0
- package/dist/mcp-server/transports/auth/strategies/authStrategy.d.ts.map +1 -0
- package/dist/mcp-server/transports/auth/strategies/authStrategy.js +2 -0
- package/dist/mcp-server/transports/auth/strategies/authStrategy.js.map +1 -0
- package/dist/mcp-server/transports/auth/strategies/jwtStrategy.d.ts +14 -0
- package/dist/mcp-server/transports/auth/strategies/jwtStrategy.d.ts.map +1 -0
- package/dist/mcp-server/transports/auth/strategies/jwtStrategy.js +86 -0
- package/dist/mcp-server/transports/auth/strategies/jwtStrategy.js.map +1 -0
- package/dist/mcp-server/transports/auth/strategies/oauthStrategy.d.ts +14 -0
- package/dist/mcp-server/transports/auth/strategies/oauthStrategy.d.ts.map +1 -0
- package/dist/mcp-server/transports/auth/strategies/oauthStrategy.js +113 -0
- package/dist/mcp-server/transports/auth/strategies/oauthStrategy.js.map +1 -0
- package/dist/mcp-server/transports/http/httpErrorHandler.d.ts +25 -0
- package/dist/mcp-server/transports/http/httpErrorHandler.d.ts.map +1 -0
- package/dist/mcp-server/transports/http/httpErrorHandler.js +112 -0
- package/dist/mcp-server/transports/http/httpErrorHandler.js.map +1 -0
- package/dist/mcp-server/transports/http/httpTransport.d.ts +47 -0
- package/dist/mcp-server/transports/http/httpTransport.d.ts.map +1 -0
- package/dist/mcp-server/transports/http/httpTransport.js +396 -0
- package/dist/mcp-server/transports/http/httpTransport.js.map +1 -0
- package/dist/mcp-server/transports/http/httpTypes.d.ts +17 -0
- package/dist/mcp-server/transports/http/httpTypes.d.ts.map +1 -0
- package/dist/mcp-server/transports/http/httpTypes.js +2 -0
- package/dist/mcp-server/transports/http/httpTypes.js.map +1 -0
- package/dist/mcp-server/transports/http/protectedResourceMetadata.d.ts +21 -0
- package/dist/mcp-server/transports/http/protectedResourceMetadata.d.ts.map +1 -0
- package/dist/mcp-server/transports/http/protectedResourceMetadata.js +44 -0
- package/dist/mcp-server/transports/http/protectedResourceMetadata.js.map +1 -0
- package/dist/mcp-server/transports/http/sessionIdUtils.d.ts +33 -0
- package/dist/mcp-server/transports/http/sessionIdUtils.d.ts.map +1 -0
- package/dist/mcp-server/transports/http/sessionIdUtils.js +54 -0
- package/dist/mcp-server/transports/http/sessionIdUtils.js.map +1 -0
- package/dist/mcp-server/transports/http/sessionStore.d.ts +87 -0
- package/dist/mcp-server/transports/http/sessionStore.d.ts.map +1 -0
- package/dist/mcp-server/transports/http/sessionStore.js +209 -0
- package/dist/mcp-server/transports/http/sessionStore.js.map +1 -0
- package/dist/mcp-server/transports/manager.d.ts +22 -0
- package/dist/mcp-server/transports/manager.d.ts.map +1 -0
- package/dist/mcp-server/transports/manager.js +62 -0
- package/dist/mcp-server/transports/manager.js.map +1 -0
- package/dist/mcp-server/transports/stdio/stdioTransport.d.ts +44 -0
- package/dist/mcp-server/transports/stdio/stdioTransport.d.ts.map +1 -0
- package/dist/mcp-server/transports/stdio/stdioTransport.js +63 -0
- package/dist/mcp-server/transports/stdio/stdioTransport.js.map +1 -0
- package/dist/services/graph/core/GraphService.d.ts +205 -0
- package/dist/services/graph/core/GraphService.d.ts.map +1 -0
- package/dist/services/graph/core/GraphService.js +231 -0
- package/dist/services/graph/core/GraphService.js.map +1 -0
- package/dist/services/graph/core/IGraphProvider.d.ts +295 -0
- package/dist/services/graph/core/IGraphProvider.d.ts.map +1 -0
- package/dist/services/graph/core/IGraphProvider.js +8 -0
- package/dist/services/graph/core/IGraphProvider.js.map +1 -0
- package/dist/services/graph/types.d.ts +107 -0
- package/dist/services/graph/types.d.ts.map +1 -0
- package/dist/services/graph/types.js +8 -0
- package/dist/services/graph/types.js.map +1 -0
- package/dist/services/llm/core/ILlmProvider.d.ts +86 -0
- package/dist/services/llm/core/ILlmProvider.d.ts.map +1 -0
- package/dist/services/llm/core/ILlmProvider.js +2 -0
- package/dist/services/llm/core/ILlmProvider.js.map +1 -0
- package/dist/services/llm/providers/openrouter.provider.d.ts +187 -0
- package/dist/services/llm/providers/openrouter.provider.d.ts.map +1 -0
- package/dist/services/llm/providers/openrouter.provider.js +302 -0
- package/dist/services/llm/providers/openrouter.provider.js.map +1 -0
- package/dist/services/llm/types.d.ts +16 -0
- package/dist/services/llm/types.d.ts.map +1 -0
- package/dist/services/llm/types.js +9 -0
- package/dist/services/llm/types.js.map +1 -0
- package/dist/services/speech/core/ISpeechProvider.d.ts +92 -0
- package/dist/services/speech/core/ISpeechProvider.d.ts.map +1 -0
- package/dist/services/speech/core/ISpeechProvider.js +34 -0
- package/dist/services/speech/core/ISpeechProvider.js.map +1 -0
- package/dist/services/speech/core/SpeechService.d.ts +87 -0
- package/dist/services/speech/core/SpeechService.d.ts.map +1 -0
- package/dist/services/speech/core/SpeechService.js +135 -0
- package/dist/services/speech/core/SpeechService.js.map +1 -0
- package/dist/services/speech/providers/elevenlabs.provider.d.ts +77 -0
- package/dist/services/speech/providers/elevenlabs.provider.d.ts.map +1 -0
- package/dist/services/speech/providers/elevenlabs.provider.js +199 -0
- package/dist/services/speech/providers/elevenlabs.provider.js.map +1 -0
- package/dist/services/speech/providers/whisper.provider.d.ts +94 -0
- package/dist/services/speech/providers/whisper.provider.d.ts.map +1 -0
- package/dist/services/speech/providers/whisper.provider.js +240 -0
- package/dist/services/speech/providers/whisper.provider.js.map +1 -0
- package/dist/services/speech/types.d.ts +173 -0
- package/dist/services/speech/types.d.ts.map +1 -0
- package/dist/services/speech/types.js +8 -0
- package/dist/services/speech/types.js.map +1 -0
- package/dist/storage/core/IStorageProvider.d.ts +159 -0
- package/dist/storage/core/IStorageProvider.d.ts.map +1 -0
- package/dist/storage/core/IStorageProvider.js +2 -0
- package/dist/storage/core/IStorageProvider.js.map +1 -0
- package/dist/storage/core/StorageService.d.ts +22 -0
- package/dist/storage/core/StorageService.d.ts.map +1 -0
- package/dist/storage/core/StorageService.js +151 -0
- package/dist/storage/core/StorageService.js.map +1 -0
- package/dist/storage/core/storageFactory.d.ts +66 -0
- package/dist/storage/core/storageFactory.d.ts.map +1 -0
- package/dist/storage/core/storageFactory.js +122 -0
- package/dist/storage/core/storageFactory.js.map +1 -0
- package/dist/storage/core/storageValidation.d.ts +77 -0
- package/dist/storage/core/storageValidation.d.ts.map +1 -0
- package/dist/storage/core/storageValidation.js +303 -0
- package/dist/storage/core/storageValidation.js.map +1 -0
- package/dist/storage/providers/cloudflare/d1Provider.d.ts +94 -0
- package/dist/storage/providers/cloudflare/d1Provider.d.ts.map +1 -0
- package/dist/storage/providers/cloudflare/d1Provider.js +347 -0
- package/dist/storage/providers/cloudflare/d1Provider.js.map +1 -0
- package/dist/storage/providers/cloudflare/kvProvider.d.ts +21 -0
- package/dist/storage/providers/cloudflare/kvProvider.d.ts.map +1 -0
- package/dist/storage/providers/cloudflare/kvProvider.js +183 -0
- package/dist/storage/providers/cloudflare/kvProvider.js.map +1 -0
- package/dist/storage/providers/cloudflare/r2Provider.d.ts +28 -0
- package/dist/storage/providers/cloudflare/r2Provider.d.ts.map +1 -0
- package/dist/storage/providers/cloudflare/r2Provider.js +222 -0
- package/dist/storage/providers/cloudflare/r2Provider.js.map +1 -0
- package/dist/storage/providers/fileSystem/fileSystemProvider.d.ts +20 -0
- package/dist/storage/providers/fileSystem/fileSystemProvider.d.ts.map +1 -0
- package/dist/storage/providers/fileSystem/fileSystemProvider.js +282 -0
- package/dist/storage/providers/fileSystem/fileSystemProvider.js.map +1 -0
- package/dist/storage/providers/inMemory/inMemoryProvider.d.ts +21 -0
- package/dist/storage/providers/inMemory/inMemoryProvider.d.ts.map +1 -0
- package/dist/storage/providers/inMemory/inMemoryProvider.js +139 -0
- package/dist/storage/providers/inMemory/inMemoryProvider.js.map +1 -0
- package/dist/storage/providers/supabase/supabase.types.d.ts +49 -0
- package/dist/storage/providers/supabase/supabase.types.d.ts.map +1 -0
- package/dist/storage/providers/supabase/supabase.types.js +8 -0
- package/dist/storage/providers/supabase/supabase.types.js.map +1 -0
- package/dist/storage/providers/supabase/supabaseProvider.d.ts +24 -0
- package/dist/storage/providers/supabase/supabaseProvider.d.ts.map +1 -0
- package/dist/storage/providers/supabase/supabaseProvider.js +209 -0
- package/dist/storage/providers/supabase/supabaseProvider.js.map +1 -0
- package/dist/testing/index.d.ts +53 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +132 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/types-global/errors.d.ts +83 -0
- package/dist/types-global/errors.d.ts.map +1 -0
- package/dist/types-global/errors.js +113 -0
- package/dist/types-global/errors.js.map +1 -0
- package/dist/utils/formatting/diffFormatter.d.ts +227 -0
- package/dist/utils/formatting/diffFormatter.d.ts.map +1 -0
- package/dist/utils/formatting/diffFormatter.js +369 -0
- package/dist/utils/formatting/diffFormatter.js.map +1 -0
- package/dist/utils/formatting/index.d.ts +9 -0
- package/dist/utils/formatting/index.d.ts.map +1 -0
- package/dist/utils/formatting/index.js +9 -0
- package/dist/utils/formatting/index.js.map +1 -0
- package/dist/utils/formatting/markdownBuilder.d.ts +543 -0
- package/dist/utils/formatting/markdownBuilder.d.ts.map +1 -0
- package/dist/utils/formatting/markdownBuilder.js +674 -0
- package/dist/utils/formatting/markdownBuilder.js.map +1 -0
- package/dist/utils/formatting/tableFormatter.d.ts +261 -0
- package/dist/utils/formatting/tableFormatter.d.ts.map +1 -0
- package/dist/utils/formatting/tableFormatter.js +456 -0
- package/dist/utils/formatting/tableFormatter.js.map +1 -0
- package/dist/utils/formatting/treeFormatter.d.ts +344 -0
- package/dist/utils/formatting/treeFormatter.d.ts.map +1 -0
- package/dist/utils/formatting/treeFormatter.js +400 -0
- package/dist/utils/formatting/treeFormatter.js.map +1 -0
- package/dist/utils/internal/encoding.d.ts +42 -0
- package/dist/utils/internal/encoding.d.ts.map +1 -0
- package/dist/utils/internal/encoding.js +87 -0
- package/dist/utils/internal/encoding.js.map +1 -0
- package/dist/utils/internal/error-handler/errorHandler.d.ts +140 -0
- package/dist/utils/internal/error-handler/errorHandler.d.ts.map +1 -0
- package/dist/utils/internal/error-handler/errorHandler.js +318 -0
- package/dist/utils/internal/error-handler/errorHandler.js.map +1 -0
- package/dist/utils/internal/error-handler/helpers.d.ts +98 -0
- package/dist/utils/internal/error-handler/helpers.d.ts.map +1 -0
- package/dist/utils/internal/error-handler/helpers.js +214 -0
- package/dist/utils/internal/error-handler/helpers.js.map +1 -0
- package/dist/utils/internal/error-handler/mappings.d.ts +85 -0
- package/dist/utils/internal/error-handler/mappings.d.ts.map +1 -0
- package/dist/utils/internal/error-handler/mappings.js +234 -0
- package/dist/utils/internal/error-handler/mappings.js.map +1 -0
- package/dist/utils/internal/error-handler/types.d.ts +160 -0
- package/dist/utils/internal/error-handler/types.d.ts.map +1 -0
- package/dist/utils/internal/error-handler/types.js +6 -0
- package/dist/utils/internal/error-handler/types.js.map +1 -0
- package/dist/utils/internal/health.d.ts +60 -0
- package/dist/utils/internal/health.d.ts.map +1 -0
- package/dist/utils/internal/health.js +46 -0
- package/dist/utils/internal/health.js.map +1 -0
- package/dist/utils/internal/logger.d.ts +300 -0
- package/dist/utils/internal/logger.d.ts.map +1 -0
- package/dist/utils/internal/logger.js +573 -0
- package/dist/utils/internal/logger.js.map +1 -0
- package/dist/utils/internal/performance.d.ts +78 -0
- package/dist/utils/internal/performance.d.ts.map +1 -0
- package/dist/utils/internal/performance.js +227 -0
- package/dist/utils/internal/performance.js.map +1 -0
- package/dist/utils/internal/requestContext.d.ts +200 -0
- package/dist/utils/internal/requestContext.d.ts.map +1 -0
- package/dist/utils/internal/requestContext.js +163 -0
- package/dist/utils/internal/requestContext.js.map +1 -0
- package/dist/utils/internal/runtime.d.ts +49 -0
- package/dist/utils/internal/runtime.d.ts.map +1 -0
- package/dist/utils/internal/runtime.js +90 -0
- package/dist/utils/internal/runtime.js.map +1 -0
- package/dist/utils/internal/startupBanner.d.ts +23 -0
- package/dist/utils/internal/startupBanner.d.ts.map +1 -0
- package/dist/utils/internal/startupBanner.js +34 -0
- package/dist/utils/internal/startupBanner.js.map +1 -0
- package/dist/utils/metrics/tokenCounter.d.ts +97 -0
- package/dist/utils/metrics/tokenCounter.d.ts.map +1 -0
- package/dist/utils/metrics/tokenCounter.js +162 -0
- package/dist/utils/metrics/tokenCounter.js.map +1 -0
- package/dist/utils/network/fetchWithTimeout.d.ts +91 -0
- package/dist/utils/network/fetchWithTimeout.d.ts.map +1 -0
- package/dist/utils/network/fetchWithTimeout.js +305 -0
- package/dist/utils/network/fetchWithTimeout.js.map +1 -0
- package/dist/utils/pagination/pagination.d.ts +157 -0
- package/dist/utils/pagination/pagination.d.ts.map +1 -0
- package/dist/utils/pagination/pagination.js +191 -0
- package/dist/utils/pagination/pagination.js.map +1 -0
- package/dist/utils/parsing/csvParser.d.ts +84 -0
- package/dist/utils/parsing/csvParser.d.ts.map +1 -0
- package/dist/utils/parsing/csvParser.js +132 -0
- package/dist/utils/parsing/csvParser.js.map +1 -0
- package/dist/utils/parsing/dateParser.d.ts +103 -0
- package/dist/utils/parsing/dateParser.d.ts.map +1 -0
- package/dist/utils/parsing/dateParser.js +142 -0
- package/dist/utils/parsing/dateParser.js.map +1 -0
- package/dist/utils/parsing/frontmatterParser.d.ts +91 -0
- package/dist/utils/parsing/frontmatterParser.d.ts.map +1 -0
- package/dist/utils/parsing/frontmatterParser.js +163 -0
- package/dist/utils/parsing/frontmatterParser.js.map +1 -0
- package/dist/utils/parsing/index.d.ts +15 -0
- package/dist/utils/parsing/index.d.ts.map +1 -0
- package/dist/utils/parsing/index.js +15 -0
- package/dist/utils/parsing/index.js.map +1 -0
- package/dist/utils/parsing/jsonParser.d.ts +115 -0
- package/dist/utils/parsing/jsonParser.d.ts.map +1 -0
- package/dist/utils/parsing/jsonParser.js +177 -0
- package/dist/utils/parsing/jsonParser.js.map +1 -0
- package/dist/utils/parsing/pdfParser.d.ts +563 -0
- package/dist/utils/parsing/pdfParser.d.ts.map +1 -0
- package/dist/utils/parsing/pdfParser.js +775 -0
- package/dist/utils/parsing/pdfParser.js.map +1 -0
- package/dist/utils/parsing/thinkBlock.d.ts +31 -0
- package/dist/utils/parsing/thinkBlock.d.ts.map +1 -0
- package/dist/utils/parsing/thinkBlock.js +31 -0
- package/dist/utils/parsing/thinkBlock.js.map +1 -0
- package/dist/utils/parsing/xmlParser.d.ts +69 -0
- package/dist/utils/parsing/xmlParser.d.ts.map +1 -0
- package/dist/utils/parsing/xmlParser.js +140 -0
- package/dist/utils/parsing/xmlParser.js.map +1 -0
- package/dist/utils/parsing/yamlParser.d.ts +64 -0
- package/dist/utils/parsing/yamlParser.d.ts.map +1 -0
- package/dist/utils/parsing/yamlParser.js +129 -0
- package/dist/utils/parsing/yamlParser.js.map +1 -0
- package/dist/utils/scheduling/scheduler.d.ts +174 -0
- package/dist/utils/scheduling/scheduler.d.ts.map +1 -0
- package/dist/utils/scheduling/scheduler.js +248 -0
- package/dist/utils/scheduling/scheduler.js.map +1 -0
- package/dist/utils/security/idGenerator.d.ts +189 -0
- package/dist/utils/security/idGenerator.d.ts.map +1 -0
- package/dist/utils/security/idGenerator.js +301 -0
- package/dist/utils/security/idGenerator.js.map +1 -0
- package/dist/utils/security/index.d.ts +8 -0
- package/dist/utils/security/index.d.ts.map +1 -0
- package/dist/utils/security/index.js +8 -0
- package/dist/utils/security/index.js.map +1 -0
- package/dist/utils/security/rateLimiter.d.ts +171 -0
- package/dist/utils/security/rateLimiter.d.ts.map +1 -0
- package/dist/utils/security/rateLimiter.js +294 -0
- package/dist/utils/security/rateLimiter.js.map +1 -0
- package/dist/utils/security/sanitization.d.ts +430 -0
- package/dist/utils/security/sanitization.d.ts.map +1 -0
- package/dist/utils/security/sanitization.js +759 -0
- package/dist/utils/security/sanitization.js.map +1 -0
- package/dist/utils/telemetry/index.d.ts +12 -0
- package/dist/utils/telemetry/index.d.ts.map +1 -0
- package/dist/utils/telemetry/index.js +12 -0
- package/dist/utils/telemetry/index.js.map +1 -0
- package/dist/utils/telemetry/instrumentation.d.ts +62 -0
- package/dist/utils/telemetry/instrumentation.d.ts.map +1 -0
- package/dist/utils/telemetry/instrumentation.js +223 -0
- package/dist/utils/telemetry/instrumentation.js.map +1 -0
- package/dist/utils/telemetry/metrics.d.ts +170 -0
- package/dist/utils/telemetry/metrics.d.ts.map +1 -0
- package/dist/utils/telemetry/metrics.js +205 -0
- package/dist/utils/telemetry/metrics.js.map +1 -0
- package/dist/utils/telemetry/semconv.d.ts +147 -0
- package/dist/utils/telemetry/semconv.d.ts.map +1 -0
- package/dist/utils/telemetry/semconv.js +159 -0
- package/dist/utils/telemetry/semconv.js.map +1 -0
- package/dist/utils/telemetry/trace.d.ts +141 -0
- package/dist/utils/telemetry/trace.d.ts.map +1 -0
- package/dist/utils/telemetry/trace.js +193 -0
- package/dist/utils/telemetry/trace.js.map +1 -0
- package/dist/utils/types/guards.d.ts +209 -0
- package/dist/utils/types/guards.d.ts.map +1 -0
- package/dist/utils/types/guards.js +229 -0
- package/dist/utils/types/guards.js.map +1 -0
- package/dist/utils/types/index.d.ts +6 -0
- package/dist/utils/types/index.d.ts.map +1 -0
- package/dist/utils/types/index.js +6 -0
- package/dist/utils/types/index.js.map +1 -0
- package/dist/worker.d.ts +59 -0
- package/dist/worker.d.ts.map +1 -0
- package/dist/worker.js +216 -0
- package/dist/worker.js.map +1 -0
- package/package.json +377 -0
- package/skills/README.md +38 -0
- package/skills/add-export/SKILL.md +49 -0
- package/skills/add-prompt/SKILL.md +97 -0
- package/skills/add-provider/SKILL.md +53 -0
- package/skills/add-resource/SKILL.md +107 -0
- package/skills/add-service/SKILL.md +113 -0
- package/skills/add-tool/SKILL.md +110 -0
- package/skills/api-auth/SKILL.md +173 -0
- package/skills/api-config/SKILL.md +68 -0
- package/skills/api-context/SKILL.md +321 -0
- package/skills/api-errors/SKILL.md +146 -0
- package/skills/api-services/SKILL.md +24 -0
- package/skills/api-services/references/graph.md +124 -0
- package/skills/api-services/references/llm.md +46 -0
- package/skills/api-services/references/speech.md +72 -0
- package/skills/api-testing/SKILL.md +263 -0
- package/skills/api-utils/SKILL.md +106 -0
- package/skills/api-utils/references/formatting.md +237 -0
- package/skills/api-utils/references/parsing.md +263 -0
- package/skills/api-utils/references/security.md +226 -0
- package/skills/api-workers/SKILL.md +165 -0
- package/skills/devcheck/SKILL.md +31 -0
- package/skills/maintenance/SKILL.md +52 -0
- package/skills/migrate-mcp-ts-template/SKILL.md +131 -0
- package/skills/release/SKILL.md +67 -0
- package/skills/setup/SKILL.md +89 -0
- package/skills/walkthrough-init/SKILL.md +50 -0
- package/templates/.env.example +17 -0
- package/templates/AGENTS.md +113 -0
- package/templates/CLAUDE.md +113 -0
- package/templates/_tsconfig.json +33 -0
- package/templates/biome.template.json +43 -0
- package/templates/package.json +26 -0
- package/templates/src/index.ts +16 -0
- package/templates/src/mcp-server/prompts/definitions/echo.prompt.ts +19 -0
- package/templates/src/mcp-server/resources/definitions/echo.resource.ts +30 -0
- package/templates/src/mcp-server/tools/definitions/echo.tool.ts +24 -0
- package/templates/vitest.config.ts +12 -0
- package/tsconfig.base.json +44 -0
- package/vitest.config.base.ts +38 -0
package/CLAUDE.md
ADDED
|
@@ -0,0 +1,583 @@
|
|
|
1
|
+
# Agent Protocol
|
|
2
|
+
|
|
3
|
+
**Package:** `@cyanheads/mcp-ts-core` · **Version:** 0.1.0
|
|
4
|
+
**npm:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) · **Docker:** [ghcr.io/cyanheads/mcp-ts-core](https://ghcr.io/cyanheads/mcp-ts-core)
|
|
5
|
+
|
|
6
|
+
> **Developer note:** Never assume. Read related files and docs before making changes. Read full file content for context. Never edit a file before reading it.
|
|
7
|
+
|
|
8
|
+
> **Extraction status:** This document describes the target API for `@cyanheads/mcp-ts-core`. See `core-extraction/` for implementation status and the Phase 3 checklist.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Core Rules
|
|
13
|
+
|
|
14
|
+
- **Logic throws, handlers catch.** Pure, stateless `handler` functions. No `try...catch`. Throw `McpError(code, message, data)` on failure. The framework creates `Context`, measures execution, formats responses, catches errors.
|
|
15
|
+
- **Full-stack observability.** OpenTelemetry preconfigured. Use `ctx.log` for request-scoped logging — `requestId`, `traceId`, `tenantId` auto-correlated. No `console` calls.
|
|
16
|
+
- **Unified Context.** Handlers receive `ctx` with logging (`ctx.log`), tenant-scoped storage (`ctx.state`), optional protocol capabilities (`ctx.elicit`, `ctx.sample`), and cancellation (`ctx.signal`).
|
|
17
|
+
- **Decoupled storage.** `ctx.state` for tenant-scoped KV. Never access persistence backends directly.
|
|
18
|
+
- **Runtime parity.** All features work with `stdio`/`http` and Worker bundle. Guard non-portable deps via `runtimeCaps`. Prefer runtime-agnostic abstractions (Hono + `@hono/mcp`, Fetch APIs).
|
|
19
|
+
- **Elicitation for missing input.** Use `ctx.elicit` when the client supports it.
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Exports Reference
|
|
24
|
+
|
|
25
|
+
| Subpath | Key Exports | Purpose |
|
|
26
|
+
|:--------|:------------|:--------|
|
|
27
|
+
| `@cyanheads/mcp-ts-core` | `createApp`, `tool`, `resource`, `prompt`, `Context` | Main entry point |
|
|
28
|
+
| `/worker` | `createWorkerHandler`, `CloudflareBindings` | Cloudflare Workers entry |
|
|
29
|
+
| `/tools` | `ToolDefinition`, `AnyToolDefinition`, `ToolAnnotations` | Tool definition types |
|
|
30
|
+
| `/resources` | `ResourceDefinition`, `AnyResourceDefinition` | Resource definition types |
|
|
31
|
+
| `/prompts` | `PromptDefinition` | Prompt definition type |
|
|
32
|
+
| `/tasks` | `TaskToolDefinition`, `isTaskToolDefinition` | Task tool escape hatch |
|
|
33
|
+
| `/context` | `Context`, `ContextLogger`, `ContextState`, `ContextProgress` | Context types |
|
|
34
|
+
| `/errors` | `McpError`, `JsonRpcErrorCode` | Error types and codes |
|
|
35
|
+
| `/config` | `AppConfig`, `parseConfig` | Zod-validated config |
|
|
36
|
+
| `/auth` | `checkScopes` | Dynamic scope checking |
|
|
37
|
+
| `/storage` | `StorageService` | Storage abstraction |
|
|
38
|
+
| `/storage/types` | `IStorageProvider` | Provider interface |
|
|
39
|
+
| `/utils/logger` | `logger` | Global Pino logger |
|
|
40
|
+
| `/utils/requestContext` | `requestContextService`, `RequestContext` | Request tracing |
|
|
41
|
+
| `/utils/errorHandler` | `ErrorHandler` | `tryCatch` for services |
|
|
42
|
+
| `/utils/formatting` | `markdown`, `MarkdownBuilder`, `diffFormatter`, `tableFormatter`, `treeFormatter` | Response formatters |
|
|
43
|
+
| `/utils/parsing` | `yamlParser`, `csvParser`, `xmlParser`, `jsonParser`, `pdfParser`, `dateParser`, `frontmatterParser` | Content parsers (Tier 3) |
|
|
44
|
+
| `/utils/security` | `sanitization`, `rateLimiter`, `idGenerator` | Security utilities (Tier 3) |
|
|
45
|
+
| `/utils/network` | `fetchWithTimeout` | HTTP client with timeout/abort |
|
|
46
|
+
| `/utils/pagination` | `extractCursor`, `paginateArray` | Opaque cursor pagination |
|
|
47
|
+
| `/utils/runtime` | `runtimeCaps` | Runtime feature detection |
|
|
48
|
+
| `/utils/scheduling` | `schedulerService` | Cron scheduling (Tier 3) |
|
|
49
|
+
| `/utils/types` | `isErrorWithCode`, `isRecord` | Type guard utilities |
|
|
50
|
+
| `/testing` | `createMockContext` | Test helpers |
|
|
51
|
+
|
|
52
|
+
All subpaths prefixed with `@cyanheads/mcp-ts-core`. **Tier 3 deps** (parsers, security, scheduling) are optional peer dependencies — install as needed. All Tier 3 methods are **async** (lazy-load deps at first call).
|
|
53
|
+
|
|
54
|
+
### Import conventions
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
// Framework (from node_modules)
|
|
58
|
+
import { tool } from '@cyanheads/mcp-ts-core';
|
|
59
|
+
import { McpError, JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
|
|
60
|
+
|
|
61
|
+
// Server's own code (via path alias)
|
|
62
|
+
import { getMyService } from '@/services/my-domain/my-service.js';
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Build configs exported for consumer extension: `tsconfig.json` extends `@cyanheads/mcp-ts-core/tsconfig.base.json`, `biome.json` extends `@cyanheads/mcp-ts-core/biome.json`, `vitest.config.ts` spreads from `@cyanheads/mcp-ts-core/vitest.config`.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Entry Points
|
|
70
|
+
|
|
71
|
+
### Node.js — `createApp(options)`
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
#!/usr/bin/env node
|
|
75
|
+
import { createApp } from '@cyanheads/mcp-ts-core';
|
|
76
|
+
import { allToolDefinitions } from './mcp-server/tools/index.js';
|
|
77
|
+
import { allResourceDefinitions } from './mcp-server/resources/index.js';
|
|
78
|
+
import { allPromptDefinitions } from './mcp-server/prompts/index.js';
|
|
79
|
+
|
|
80
|
+
await createApp({
|
|
81
|
+
name: 'my-mcp-server', // overrides package.json / MCP_SERVER_NAME
|
|
82
|
+
version: '0.1.0', // overrides package.json / MCP_SERVER_VERSION
|
|
83
|
+
tools: allToolDefinitions,
|
|
84
|
+
resources: allResourceDefinitions,
|
|
85
|
+
prompts: allPromptDefinitions,
|
|
86
|
+
setup(core) { // runs after core services init, before transport starts
|
|
87
|
+
initMyService(core.config, core.storage);
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Cloudflare Workers — `createWorkerHandler(options)`
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
import { createWorkerHandler } from '@cyanheads/mcp-ts-core/worker';
|
|
96
|
+
|
|
97
|
+
export default createWorkerHandler({
|
|
98
|
+
tools: allToolDefinitions,
|
|
99
|
+
resources: allResourceDefinitions,
|
|
100
|
+
prompts: allPromptDefinitions,
|
|
101
|
+
setup(core) { initMyService(core.config, core.storage); },
|
|
102
|
+
extraEnvBindings: [['MY_API_KEY', 'MY_API_KEY']], // string values → process.env
|
|
103
|
+
extraObjectBindings: [['MY_CUSTOM_KV', 'MY_CUSTOM_KV']], // KV/R2/D1 → globalThis
|
|
104
|
+
onScheduled: async (controller, env, ctx) => { /* cron */ },
|
|
105
|
+
});
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Key design: per-request `McpServer` factory (security: SDK GHSA-345p-7cg4-v4c7), env bindings refreshed per-request, `ctx.waitUntil()` for telemetry flush. Requires `compatibility_flags = ["nodejs_compat"]` and `compatibility_date >= "2025-09-01"` in `wrangler.toml`. Only `in-memory`, `cloudflare-r2`, `cloudflare-kv`, `cloudflare-d1` storage providers in Workers.
|
|
109
|
+
|
|
110
|
+
### Interfaces
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
interface CreateAppOptions {
|
|
114
|
+
name?: string;
|
|
115
|
+
version?: string;
|
|
116
|
+
tools?: AnyToolDefinition[];
|
|
117
|
+
resources?: AnyResourceDefinition[];
|
|
118
|
+
prompts?: PromptDefinition[];
|
|
119
|
+
setup?: (core: CoreServices) => void | Promise<void>;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
interface CoreServices {
|
|
123
|
+
config: AppConfig;
|
|
124
|
+
logger: Logger;
|
|
125
|
+
storage: StorageService;
|
|
126
|
+
rateLimiter: RateLimiter;
|
|
127
|
+
llmProvider?: ILlmProvider;
|
|
128
|
+
speechService?: SpeechService;
|
|
129
|
+
supabase?: SupabaseClient;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
interface ServerHandle {
|
|
133
|
+
shutdown(signal?: string): Promise<void>;
|
|
134
|
+
readonly services: CoreServices;
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## Server Structure
|
|
141
|
+
|
|
142
|
+
```
|
|
143
|
+
src/
|
|
144
|
+
index.ts # createApp() entry point
|
|
145
|
+
worker.ts # createWorkerHandler() (if using Workers)
|
|
146
|
+
config/
|
|
147
|
+
server-config.ts # Server-specific env vars (own Zod schema)
|
|
148
|
+
services/
|
|
149
|
+
[domain]/
|
|
150
|
+
[domain]-service.ts # Domain service (init/accessor pattern)
|
|
151
|
+
types.ts # Domain types
|
|
152
|
+
mcp-server/
|
|
153
|
+
tools/definitions/
|
|
154
|
+
[tool-name].tool.ts # Tool definitions
|
|
155
|
+
index.ts # allToolDefinitions barrel
|
|
156
|
+
resources/definitions/
|
|
157
|
+
[resource-name].resource.ts # Resource definitions
|
|
158
|
+
index.ts # allResourceDefinitions barrel
|
|
159
|
+
prompts/definitions/
|
|
160
|
+
[prompt-name].prompt.ts # Prompt definitions
|
|
161
|
+
index.ts # allPromptDefinitions barrel
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
**File suffixes:** `.tool.ts` (standard or task), `.resource.ts`, `.prompt.ts`, `.app-tool.ts` (UI-enabled), `.app-resource.ts` (UI resource linked to app tool).
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## Adding a Tool
|
|
169
|
+
|
|
170
|
+
```ts
|
|
171
|
+
import { z } from 'zod';
|
|
172
|
+
import { tool } from '@cyanheads/mcp-ts-core';
|
|
173
|
+
import { McpError, JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
|
|
174
|
+
|
|
175
|
+
export const myTool = tool('my_tool', {
|
|
176
|
+
description: 'Does something useful.',
|
|
177
|
+
annotations: { readOnlyHint: true },
|
|
178
|
+
input: z.object({ query: z.string().describe('Search query') }),
|
|
179
|
+
output: z.object({ result: z.string().describe('Search result') }),
|
|
180
|
+
auth: ['tool:my_tool:read'],
|
|
181
|
+
|
|
182
|
+
async handler(input, ctx) {
|
|
183
|
+
ctx.log.info('Processing query', { query: input.query });
|
|
184
|
+
return { result: `Found: ${input.query}` };
|
|
185
|
+
},
|
|
186
|
+
|
|
187
|
+
format: (result) => [{ type: 'text', text: result.result }],
|
|
188
|
+
});
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
**Steps:** Create `src/mcp-server/tools/definitions/[name].tool.ts` (kebab-case) → use `tool('snake_case', {...})` with Zod `.describe()` on all fields → implement `handler(input, ctx)` (pure, throws `McpError`) → add `auth`/`format` if needed → register in `definitions/index.ts` → `bun run devcheck` → smoke-test with `dev:stdio`/`dev:http`.
|
|
192
|
+
|
|
193
|
+
**`format`**: Maps output to `ContentBlock[]`. Omit for JSON stringify default. Additional formatters: `markdown()` (builder), `diffFormatter` (async), `tableFormatter`, `treeFormatter` from `/utils/formatting`.
|
|
194
|
+
|
|
195
|
+
### Task tools
|
|
196
|
+
|
|
197
|
+
Add `task: true` for long-running async operations. The framework manages the full lifecycle.
|
|
198
|
+
|
|
199
|
+
```ts
|
|
200
|
+
const asyncCountdown = tool('async_countdown', {
|
|
201
|
+
description: 'Count down with progress updates.',
|
|
202
|
+
task: true,
|
|
203
|
+
input: z.object({
|
|
204
|
+
count: z.number().int().positive().describe('Count down from'),
|
|
205
|
+
delayMs: z.number().default(1000).describe('Delay between counts in ms'),
|
|
206
|
+
}),
|
|
207
|
+
async handler(input, ctx) {
|
|
208
|
+
await ctx.progress!.setTotal(input.count);
|
|
209
|
+
for (let i = input.count; i > 0; i--) {
|
|
210
|
+
if (ctx.signal.aborted) break;
|
|
211
|
+
await ctx.progress!.update(`Counting: ${i}`);
|
|
212
|
+
await new Promise(resolve => setTimeout(resolve, input.delayMs));
|
|
213
|
+
await ctx.progress!.increment();
|
|
214
|
+
}
|
|
215
|
+
return { finalCount: 0, message: 'Countdown complete' };
|
|
216
|
+
},
|
|
217
|
+
});
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
With `task: true`: creates task → returns task ID immediately → runs handler in background with `ctx.progress` → returns status on poll → stores result/error → signals `ctx.signal` on cancellation. **Escape hatch:** `TaskToolDefinition` from `/tasks` for custom lifecycle.
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
## Adding a Resource
|
|
225
|
+
|
|
226
|
+
```ts
|
|
227
|
+
import { z } from 'zod';
|
|
228
|
+
import { resource } from '@cyanheads/mcp-ts-core';
|
|
229
|
+
|
|
230
|
+
export const myResource = resource('myscheme://{itemId}/data', {
|
|
231
|
+
description: 'Retrieve item data by ID.',
|
|
232
|
+
mimeType: 'application/json',
|
|
233
|
+
params: z.object({ itemId: z.string().describe('Item identifier') }),
|
|
234
|
+
auth: ['item:read'],
|
|
235
|
+
async handler(params, ctx) {
|
|
236
|
+
return { id: params.itemId, status: 'active' };
|
|
237
|
+
},
|
|
238
|
+
list: async () => ({
|
|
239
|
+
resources: [{ uri: 'myscheme://all', name: 'All Items', mimeType: 'application/json' }],
|
|
240
|
+
}),
|
|
241
|
+
});
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
Handler receives `(params, ctx)` — URI on `ctx.uri` if needed. Large lists must use `extractCursor`/`paginateArray` from `/utils/pagination`. Opaque cursors; invalid → `InvalidParams` (-32602).
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
## Adding a Prompt
|
|
249
|
+
|
|
250
|
+
```ts
|
|
251
|
+
import { z } from 'zod';
|
|
252
|
+
import { prompt } from '@cyanheads/mcp-ts-core';
|
|
253
|
+
|
|
254
|
+
export const codeReview = prompt('code_review', {
|
|
255
|
+
description: 'Review code for security and best practices.',
|
|
256
|
+
args: z.object({
|
|
257
|
+
code: z.string().describe('Code to review'),
|
|
258
|
+
language: z.string().optional().describe('Programming language'),
|
|
259
|
+
}),
|
|
260
|
+
generate: (args) => [
|
|
261
|
+
{ role: 'user', content: { type: 'text', text: `Review this ${args.language ?? ''} code:\n${args.code}` } },
|
|
262
|
+
],
|
|
263
|
+
});
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
Prompts are pure message templates — no `Context`, no auth, no side effects.
|
|
267
|
+
|
|
268
|
+
---
|
|
269
|
+
|
|
270
|
+
## Adding a Service
|
|
271
|
+
|
|
272
|
+
Init/accessor pattern — initialized in `setup()`, accessed at request time.
|
|
273
|
+
|
|
274
|
+
```ts
|
|
275
|
+
// src/services/my-domain/my-service.ts
|
|
276
|
+
import type { AppConfig } from '@cyanheads/mcp-ts-core/config';
|
|
277
|
+
import type { StorageService } from '@cyanheads/mcp-ts-core/storage';
|
|
278
|
+
import type { Context } from '@cyanheads/mcp-ts-core';
|
|
279
|
+
import { McpError, JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
|
|
280
|
+
|
|
281
|
+
export class MyService {
|
|
282
|
+
constructor(private readonly config: AppConfig, private readonly storage: StorageService) {}
|
|
283
|
+
async doWork(input: string, ctx: Context): Promise<string> {
|
|
284
|
+
ctx.log.debug('Working', { input });
|
|
285
|
+
return `done: ${input}`;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
let _service: MyService | undefined;
|
|
290
|
+
export function initMyService(config: AppConfig, storage: StorageService): void {
|
|
291
|
+
_service = new MyService(config, storage);
|
|
292
|
+
}
|
|
293
|
+
export function getMyService(): MyService {
|
|
294
|
+
if (!_service) throw new McpError(JsonRpcErrorCode.InitializationFailed, 'MyService not initialized');
|
|
295
|
+
return _service;
|
|
296
|
+
}
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
Usage: `getMyService().doWork(input.query, ctx)`. Service methods receive `Context` for correlated logging and tenant-scoped storage. Convention: `ctx.elicit`/`ctx.sample` only from tool handlers, not services.
|
|
300
|
+
|
|
301
|
+
---
|
|
302
|
+
|
|
303
|
+
## Context
|
|
304
|
+
|
|
305
|
+
```ts
|
|
306
|
+
interface Context {
|
|
307
|
+
readonly requestId: string;
|
|
308
|
+
readonly timestamp: string;
|
|
309
|
+
readonly tenantId?: string;
|
|
310
|
+
readonly traceId?: string;
|
|
311
|
+
readonly spanId?: string;
|
|
312
|
+
readonly auth?: AuthContext;
|
|
313
|
+
readonly log: ContextLogger; // auto-correlated: requestId, traceId, tenantId
|
|
314
|
+
readonly state: ContextState; // tenant-scoped KV storage
|
|
315
|
+
readonly elicit?: (message: string, schema: z.ZodObject<any>) => Promise<ElicitResult>;
|
|
316
|
+
readonly sample?: (messages: SamplingMessage[], opts?: SamplingOpts) => Promise<CreateMessageResult>;
|
|
317
|
+
readonly signal: AbortSignal; // cancellation
|
|
318
|
+
readonly progress?: ContextProgress; // present when task: true
|
|
319
|
+
readonly uri?: URL; // present for resource handlers
|
|
320
|
+
}
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
### `ctx.log`
|
|
324
|
+
|
|
325
|
+
Methods: `debug`, `info`, `notice`, `warning`, `error`. Use `ctx.log` in handlers; global `logger` for startup/shutdown/background.
|
|
326
|
+
|
|
327
|
+
### `ctx.state`
|
|
328
|
+
|
|
329
|
+
```ts
|
|
330
|
+
await ctx.state.set('item:123', JSON.stringify(data));
|
|
331
|
+
const value = await ctx.state.get('item:123'); // string | null
|
|
332
|
+
await ctx.state.delete('item:123');
|
|
333
|
+
const page = await ctx.state.list('item:', { cursor, limit: 20 }); // { items, cursor? }
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
Throws `McpError(InvalidRequest)` if `tenantId` missing. Stdio defaults to `'default'`. Workers with `in-memory` lose data between cold starts — use `cloudflare-kv`/`cloudflare-r2`/`cloudflare-d1` for persistence.
|
|
337
|
+
|
|
338
|
+
**Tenant ID** comes from JWT `'tid'` claim (HTTP) or `'default'` (stdio). Validation: max 128 chars, alphanumeric/hyphens/underscores/dots, start/end alphanumeric, no `../`, no consecutive dots.
|
|
339
|
+
|
|
340
|
+
### `ctx.elicit` / `ctx.sample`
|
|
341
|
+
|
|
342
|
+
Check for presence before calling:
|
|
343
|
+
|
|
344
|
+
```ts
|
|
345
|
+
if (ctx.elicit) {
|
|
346
|
+
const result = await ctx.elicit('What format?', z.object({
|
|
347
|
+
format: z.enum(['json', 'csv']).describe('Output format'),
|
|
348
|
+
}));
|
|
349
|
+
if (result.action === 'accept') useFormat(result.data.format);
|
|
350
|
+
}
|
|
351
|
+
if (ctx.sample) {
|
|
352
|
+
const result = await ctx.sample([
|
|
353
|
+
{ role: 'user', content: { type: 'text', text: `Summarize: ${data}` } },
|
|
354
|
+
], { maxTokens: 500 });
|
|
355
|
+
}
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
### `ctx.progress`
|
|
359
|
+
|
|
360
|
+
Present when `task: true`. Methods: `setTotal(n)`, `increment(amount?)`, `update(message)`.
|
|
361
|
+
|
|
362
|
+
---
|
|
363
|
+
|
|
364
|
+
## Error Handling
|
|
365
|
+
|
|
366
|
+
```ts
|
|
367
|
+
throw new McpError(JsonRpcErrorCode.InvalidParams, 'Missing required field: name', {
|
|
368
|
+
requestId: ctx.requestId, field: 'name',
|
|
369
|
+
});
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
| Code | Value | When to Use |
|
|
373
|
+
|:-----|------:|:------------|
|
|
374
|
+
| `InvalidParams` | -32602 | Bad input, missing fields, schema validation |
|
|
375
|
+
| `InvalidRequest` | -32600 | Unsupported operation, missing client capability |
|
|
376
|
+
| `NotFound` | -32001 | Resource/entity doesn't exist |
|
|
377
|
+
| `Forbidden` | -32005 | Authenticated but insufficient scopes |
|
|
378
|
+
| `Unauthorized` | -32006 | No auth, invalid/expired token |
|
|
379
|
+
| `RateLimited` | -32003 | Rate limit exceeded |
|
|
380
|
+
| `ServiceUnavailable` | -32000 | External dependency down |
|
|
381
|
+
| `Timeout` | -32004 | Operation exceeded time limit |
|
|
382
|
+
| `ConfigurationError` | -32008 | Missing env var, invalid config |
|
|
383
|
+
| `ValidationError` | -32007 | Business rule violation (not schema) |
|
|
384
|
+
| `Conflict` | -32002 | Duplicate key, version mismatch |
|
|
385
|
+
| `InitializationFailed` | -32009 | Startup failure |
|
|
386
|
+
| `DatabaseError` | -32010 | Storage layer failure |
|
|
387
|
+
| `InternalError` | -32603 | Catch-all for programmer errors |
|
|
388
|
+
|
|
389
|
+
**Where handled:** Tool/resource handlers throw `McpError` (no try/catch) → handler factory catches, normalizes, sets `isError: true` → services use `ErrorHandler.tryCatch` for recovery.
|
|
390
|
+
|
|
391
|
+
---
|
|
392
|
+
|
|
393
|
+
## Auth
|
|
394
|
+
|
|
395
|
+
Inline `auth` on definitions (primary pattern):
|
|
396
|
+
|
|
397
|
+
```ts
|
|
398
|
+
const myTool = tool('my_tool', {
|
|
399
|
+
auth: ['tool:my_tool:read'],
|
|
400
|
+
async handler(input, ctx) { ... },
|
|
401
|
+
});
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
Handler factory checks `ctx.auth.scopes` before calling handler. Dynamic: `checkScopes(ctx, ['team:${id}:write'])` from `/auth`.
|
|
405
|
+
|
|
406
|
+
**Modes** (`MCP_AUTH_MODE`): `none` (default) | `jwt` (local secret via `MCP_AUTH_SECRET_KEY`) | `oauth` (JWKS via `OAUTH_ISSUER_URL`, `OAUTH_AUDIENCE`). Claims: `clientId` (cid/client_id), `scopes` (scp/scope), `sub`, `tenantId` (tid). Unprotected endpoints: `/healthz`, `GET /mcp`. CORS: `MCP_ALLOWED_ORIGINS` or `*`. Stdio: no HTTP auth.
|
|
407
|
+
|
|
408
|
+
---
|
|
409
|
+
|
|
410
|
+
## Configuration
|
|
411
|
+
|
|
412
|
+
### Core config
|
|
413
|
+
|
|
414
|
+
Managed by `@cyanheads/mcp-ts-core`. Validated via Zod. Precedence: `createApp()` overrides > env vars > `package.json`.
|
|
415
|
+
|
|
416
|
+
| Category | Key Variables |
|
|
417
|
+
|:---------|:-------------|
|
|
418
|
+
| Transport | `MCP_TRANSPORT_TYPE` (`stdio`\|`http`), `MCP_HTTP_PORT`, `MCP_HTTP_HOST`, `MCP_HTTP_ENDPOINT_PATH` |
|
|
419
|
+
| Auth | `MCP_AUTH_MODE`, `MCP_AUTH_SECRET_KEY`, `OAUTH_*` |
|
|
420
|
+
| Storage | `STORAGE_PROVIDER_TYPE` (`in-memory`\|`filesystem`\|`supabase`\|`cloudflare-r2`\|`cloudflare-kv`\|`cloudflare-d1`) |
|
|
421
|
+
| LLM | `OPENROUTER_API_KEY`, `OPENROUTER_APP_URL/NAME`, `LLM_DEFAULT_*` |
|
|
422
|
+
| Telemetry | `OTEL_ENABLED`, `OTEL_SERVICE_NAME/VERSION`, `OTEL_EXPORTER_OTLP_*` |
|
|
423
|
+
|
|
424
|
+
### Server config (separate schema)
|
|
425
|
+
|
|
426
|
+
Own Zod schema for domain-specific env vars. **Never merge with core's schema.** Lazy-parse — do not eagerly parse `process.env` at top-level (Workers inject env at request time via `injectEnvVars()`).
|
|
427
|
+
|
|
428
|
+
```ts
|
|
429
|
+
// src/config/server-config.ts
|
|
430
|
+
const ServerConfigSchema = z.object({
|
|
431
|
+
myApiKey: z.string().describe('External API key'),
|
|
432
|
+
maxResults: z.coerce.number().default(100),
|
|
433
|
+
});
|
|
434
|
+
let _config: ServerConfig | undefined;
|
|
435
|
+
export function getServerConfig(): ServerConfig {
|
|
436
|
+
_config ??= ServerConfigSchema.parse({ myApiKey: process.env.MY_API_KEY, maxResults: process.env.MY_MAX_RESULTS });
|
|
437
|
+
return _config;
|
|
438
|
+
}
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
---
|
|
442
|
+
|
|
443
|
+
## Testing
|
|
444
|
+
|
|
445
|
+
```ts
|
|
446
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
447
|
+
import { createMockContext } from '@cyanheads/mcp-ts-core/testing';
|
|
448
|
+
import { McpError } from '@cyanheads/mcp-ts-core/errors';
|
|
449
|
+
import { myTool } from '@/mcp-server/tools/definitions/my-tool.tool.js';
|
|
450
|
+
|
|
451
|
+
describe('myTool', () => {
|
|
452
|
+
it('returns expected output', async () => {
|
|
453
|
+
const ctx = createMockContext();
|
|
454
|
+
const result = await myTool.handler(myTool.input.parse({ query: 'hello' }), ctx);
|
|
455
|
+
expect(result.result).toBe('Found: hello');
|
|
456
|
+
});
|
|
457
|
+
it('throws McpError on invalid state', async () => {
|
|
458
|
+
await expect(myTool.handler(myTool.input.parse({ query: 'BAD' }), createMockContext())).rejects.toThrow(McpError);
|
|
459
|
+
});
|
|
460
|
+
});
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
**`createMockContext` options:** `createMockContext()` (minimal), `{ tenantId: 'test-tenant' }` (enables state), `{ sample: vi.fn() }`, `{ elicit: vi.fn() }`, `{ progress: true }` (task progress).
|
|
464
|
+
|
|
465
|
+
**Vitest config:** Extend core config, add `@/` alias: `resolve: { alias: { '@/': new URL('./src/', import.meta.url).pathname } }`.
|
|
466
|
+
|
|
467
|
+
**Isolation:** Construct deps in `beforeEach`. Re-init services per suite. Vitest runs files in separate workers.
|
|
468
|
+
|
|
469
|
+
---
|
|
470
|
+
|
|
471
|
+
## API Quick References
|
|
472
|
+
|
|
473
|
+
Detailed method signatures, options, and examples live in skill files. Read the relevant skill before starting a task it covers.
|
|
474
|
+
|
|
475
|
+
| Skill | Path | Covers |
|
|
476
|
+
|:------|:-----|:-------|
|
|
477
|
+
| `api-utils` | `skills/api-utils/SKILL.md` | formatting, parsing, security, network, pagination, runtime, scheduling, types, logger, requestContext, errorHandler, telemetry |
|
|
478
|
+
| `api-services` | `skills/api-services/SKILL.md` | LLM (OpenRouter), Speech (ElevenLabs TTS, Whisper STT), Graph (CRUD, traversal, pathfinding) |
|
|
479
|
+
| `api-context` | `skills/api-context/SKILL.md` | Context interface, createContext, ContextLogger/State/Progress |
|
|
480
|
+
| `api-errors` | `skills/api-errors/SKILL.md` | McpError, JsonRpcErrorCode, error handling patterns |
|
|
481
|
+
| `api-auth` | `skills/api-auth/SKILL.md` | Auth modes, scopes, JWT/OAuth strategies |
|
|
482
|
+
| `api-config` | `skills/api-config/SKILL.md` | AppConfig, parseConfig, env vars |
|
|
483
|
+
| `api-testing` | `skills/api-testing/SKILL.md` | createMockContext, test patterns, MockContextOptions |
|
|
484
|
+
| `api-workers` | `skills/api-workers/SKILL.md` | createWorkerHandler, CloudflareBindings, Worker runtime |
|
|
485
|
+
| `add-tool` | `skills/add-tool/SKILL.md` | Scaffold a new MCP tool definition |
|
|
486
|
+
| `add-resource` | `skills/add-resource/SKILL.md` | Scaffold a new MCP resource definition |
|
|
487
|
+
| `add-prompt` | `skills/add-prompt/SKILL.md` | Scaffold a new MCP prompt definition |
|
|
488
|
+
| `add-service` | `skills/add-service/SKILL.md` | Scaffold a new domain service |
|
|
489
|
+
| `add-provider` | `skills/add-provider/SKILL.md` | Add a new provider implementation |
|
|
490
|
+
| `add-export` | `skills/add-export/SKILL.md` | Add a new subpath export |
|
|
491
|
+
| `setup` | `skills/setup/SKILL.md` | Initialize a new consumer server from the template |
|
|
492
|
+
| `devcheck` | `skills/devcheck/SKILL.md` | Run lint, format, typecheck, security checks |
|
|
493
|
+
| `release` | `skills/release/SKILL.md` | Version bump, changelog, publish workflow |
|
|
494
|
+
| `maintenance` | `skills/maintenance/SKILL.md` | Dependency updates, housekeeping tasks |
|
|
495
|
+
| `migrate-mcp-ts-template` | `skills/migrate-mcp-ts-template/SKILL.md` | Migrate legacy template fork to package dependency |
|
|
496
|
+
|
|
497
|
+
---
|
|
498
|
+
|
|
499
|
+
## Code Style
|
|
500
|
+
|
|
501
|
+
- **Validation:** Zod schemas, all fields need `.describe()`
|
|
502
|
+
- **Logging:** `ctx.log` in handlers, global `logger` for lifecycle/background
|
|
503
|
+
- **Errors:** handlers throw `McpError`, framework catches. `ErrorHandler.tryCatch` for services only.
|
|
504
|
+
- **Secrets:** server config only — no hardcoded credentials
|
|
505
|
+
- **Naming:** kebab-case files, snake_case tool/resource/prompt names, correct suffix
|
|
506
|
+
- **JSDoc:** `@fileoverview` + `@module` required on every file
|
|
507
|
+
- **No fabricated signal:** Don't invent synthetic scores or arbitrary "confidence percentages." Surface real signal.
|
|
508
|
+
|
|
509
|
+
---
|
|
510
|
+
|
|
511
|
+
## Git
|
|
512
|
+
|
|
513
|
+
**Safety:** NEVER `git stash`. NEVER destructive commands (`reset --hard`, `checkout -- .`, `restore .`, `clean -f`) unless user explicitly requests. Read-only is always safe.
|
|
514
|
+
|
|
515
|
+
**Commits:** Plain `-m` strings, no heredoc/command substitution. [Conventional Commits](https://www.conventionalcommits.org/): `feat|fix|refactor|chore|docs|test|build(scope): message`. Group related changes atomically.
|
|
516
|
+
|
|
517
|
+
---
|
|
518
|
+
|
|
519
|
+
## Commands
|
|
520
|
+
|
|
521
|
+
| Command | Purpose |
|
|
522
|
+
|:--------|:--------|
|
|
523
|
+
| `bun run build` | Build library output (`tsc && tsc-alias`) |
|
|
524
|
+
| `bun run devcheck` | **Use often.** Lint, format, typecheck, security |
|
|
525
|
+
| `bun run test` | Unit/integration tests |
|
|
526
|
+
| `bun run dev:stdio` | Development mode (stdio) |
|
|
527
|
+
| `bun run dev:http` | Development mode (HTTP) |
|
|
528
|
+
| `bun run start:stdio` | Production mode (stdio, after build) |
|
|
529
|
+
| `bun run start:http` | Production mode (HTTP, after build) |
|
|
530
|
+
|
|
531
|
+
---
|
|
532
|
+
|
|
533
|
+
## Publishing
|
|
534
|
+
|
|
535
|
+
After version bump and final commit:
|
|
536
|
+
|
|
537
|
+
```bash
|
|
538
|
+
bun publish --access public
|
|
539
|
+
|
|
540
|
+
docker buildx build --platform linux/amd64,linux/arm64 \
|
|
541
|
+
-t ghcr.io/cyanheads/mcp-ts-core:<version> \
|
|
542
|
+
-t ghcr.io/cyanheads/mcp-ts-core:latest \
|
|
543
|
+
--push .
|
|
544
|
+
|
|
545
|
+
mcp-publisher publish
|
|
546
|
+
```
|
|
547
|
+
|
|
548
|
+
---
|
|
549
|
+
|
|
550
|
+
## Code Navigation
|
|
551
|
+
|
|
552
|
+
**LSP tools are deferred — load them first.** Run `ToolSearch("select:LSP")` at session start for any code nav/refactoring work.
|
|
553
|
+
|
|
554
|
+
**Grep/Glob** for file discovery, text patterns, regex. **LSP** for symbol identity, types, structure, references, call chains (`goToDefinition`, `findReferences`, `hover`, `documentSymbol`, `goToImplementation`, `incomingCalls`/`outgoingCalls`).
|
|
555
|
+
|
|
556
|
+
---
|
|
557
|
+
|
|
558
|
+
## Subagent Rules
|
|
559
|
+
|
|
560
|
+
**Default: do the work yourself.** Only spawn agents when: (1) work spans 3+ files with independent scopes, (2) you can write precise self-contained prompts, (3) parallelism adds genuine value.
|
|
561
|
+
|
|
562
|
+
When used: `model: "opus"` (preferred) or `"sonnet"` (never `haiku`). Always `run_in_background: true`. Non-overlapping file scope per agent. Agent output not visible to user — orchestrator reports findings. No git commands that modify state.
|
|
563
|
+
|
|
564
|
+
**Required agent preamble:** "CRITICAL: Do NOT run any git commands that modify state. No commits, stashes, resets, checkouts, or clean. Git is handled by the orchestrator. Read-only commands (status, diff, log, show) are acceptable."
|
|
565
|
+
|
|
566
|
+
---
|
|
567
|
+
|
|
568
|
+
## Checklist
|
|
569
|
+
|
|
570
|
+
- [ ] `tool()`/`resource()`/`prompt()` builders with correct fields (`handler`, `input`, `output`, `format`, `auth`, `args`)
|
|
571
|
+
- [ ] Zod schemas: all fields have `.describe()`
|
|
572
|
+
- [ ] JSDoc `@fileoverview` + `@module` on every new/modified file
|
|
573
|
+
- [ ] Auth via `auth: ['scope']` on definitions (not HOF wrapper)
|
|
574
|
+
- [ ] `ctx.log` for logging, `ctx.state` for storage
|
|
575
|
+
- [ ] `ctx.elicit`/`ctx.sample` checked for presence before use
|
|
576
|
+
- [ ] Naming: kebab-case files, snake_case names, correct suffixes
|
|
577
|
+
- [ ] Task tools use `task: true` flag
|
|
578
|
+
- [ ] Large resource lists: `extractCursor`/`paginateArray`
|
|
579
|
+
- [ ] Secrets only in server config
|
|
580
|
+
- [ ] Registered in `definitions/index.ts` barrel
|
|
581
|
+
- [ ] Tests added — `createMockContext()`, `.handler()` tested directly
|
|
582
|
+
- [ ] **`bun run devcheck` passes**
|
|
583
|
+
- [ ] Smoke-tested with `dev:stdio`/`dev:http`
|