tools.ts 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. /**
  2. * Three shared tools adapt model arguments to scoped resource operations.
  3. *
  4. * @module @deepseek-ai/dsh-mcp-resources
  5. */
  6. import type { Context } from '@deepseek-ai/cordis'
  7. import { defineTool, type ToolExecution } from '@deepseek-ai/dsh-tools'
  8. import type { JsonValue } from '@deepseek-ai/dsh-util-values'
  9. import type { McpResourceRequest } from './index.ts'
  10. import { renderResourceResult } from './render.ts'
  11. type RequestResource = (server: string, request: McpResourceRequest, exec: ToolExecution) => Promise<JsonValue>
  12. const listParameters = {
  13. server: { type: 'string', required: true, description: 'Configured MCP server name.' },
  14. cursor: { type: 'string', description: 'Continuation cursor returned by this server.' },
  15. } as const
  16. const output = {
  17. schema: { type: 'json' } as const,
  18. render: (args: { server: string }, value: JsonValue) => renderResourceResult(args.server, value),
  19. }
  20. /**
  21. * Register resource operations in the consumer's tool scope.
  22. * @param ctx - context owning the tool registrations.
  23. * @param request - caller-aware resource operation.
  24. * @returns the effect disposer that removes all three tools synchronously.
  25. */
  26. export function registerResourceTools(ctx: Context, request: RequestResource): () => void {
  27. const dispose = ctx.effect(function* () {
  28. yield ctx.tools.register(defineTool({
  29. name: 'list_mcp_resources',
  30. description: 'List resources available from an MCP server.',
  31. parameters: listParameters,
  32. output,
  33. execute: (args, exec) => request(args.server, {
  34. method: 'resources/list', ...args.cursor === undefined ? {} : { cursor: args.cursor },
  35. }, exec),
  36. }))
  37. yield ctx.tools.register(defineTool({
  38. name: 'list_mcp_resource_templates',
  39. description: 'List parameterized resource URI templates from an MCP server.',
  40. parameters: listParameters,
  41. output,
  42. execute: (args, exec) => request(args.server, {
  43. method: 'resources/templates/list', ...args.cursor === undefined ? {} : { cursor: args.cursor },
  44. }, exec),
  45. }))
  46. yield ctx.tools.register(defineTool({
  47. name: 'read_mcp_resource',
  48. description: 'Read an MCP resource by URI from the named server. Use a listed URI or an expanded resource template.',
  49. parameters: {
  50. server: listParameters.server,
  51. uri: { type: 'string', required: true, description: 'Resource URI to read.' },
  52. },
  53. output,
  54. execute: (args, exec) => request(args.server, { method: 'resources/read', uri: args.uri }, exec),
  55. }))
  56. }, 'mcpResources.resourceTools')
  57. // oxlint-disable-next-line typescript/no-misused-promises -- all collected tool disposers are synchronous
  58. return dispose
  59. }