Skip to content
This repository was archived by the owner on Jul 29, 2025. It is now read-only.

Commit f8a02e1

Browse files
authored
feat(server-shared): support pagination (#11)
1 parent 48b51f6 commit f8a02e1

File tree

2 files changed

+51
-20
lines changed

2 files changed

+51
-20
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import type { PaginatedRequest, PaginatedResult } from '@xsmcp/shared'
2+
3+
import { METHOD_NOT_FOUND } from '@xsmcp/shared'
4+
5+
import { XSMCPError } from './error'
6+
7+
/** @see {@link https://modelcontextprotocol.io/specification/2025-03-26/server/utilities/pagination} */
8+
export const withPagination = <T>(items: T[], params: PaginatedRequest['params']): PaginatedResult & { result: T[] } => {
9+
let currentPage: number = 0
10+
11+
if (params?.cursor != null) {
12+
try {
13+
// eslint-disable-next-line @masknet/no-builtin-base64
14+
currentPage = Number.parseInt(atob(params.cursor))
15+
}
16+
catch {
17+
throw new XSMCPError(`Cursor not found: ${params.cursor}`, METHOD_NOT_FOUND, 404)
18+
}
19+
}
20+
21+
const nextPage = currentPage + 20
22+
23+
const result = items.slice(currentPage, nextPage)
24+
25+
return {
26+
// eslint-disable-next-line @masknet/no-builtin-base64
27+
nextCursor: nextPage < items.length ? btoa(nextPage.toString()) : undefined,
28+
result,
29+
}
30+
}

packages/server-shared/src/utils/server.ts

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import type { ResourceOptions } from './resource'
2626
import type { ToolOptions } from './tool'
2727

2828
import { MethodNotFound } from './error'
29+
import { withPagination } from './pagination'
2930
import { listPrompt } from './prompt'
3031
import { listResource } from './resource'
3132
import { listTool } from './tool'
@@ -166,36 +167,36 @@ export class Server {
166167
}
167168
}
168169

169-
// TODO: support params (cursor)
170170
/** @see {@link https://modelcontextprotocol.io/specification/2025-03-26/server/prompts#listing-prompts} */
171-
public async listPrompts(_params?: ListPromptsRequest['params']): Promise<ListPromptsResult> {
172-
return {
173-
prompts: await Promise.all(this.prompts.map(async promptOptions => listPrompt(promptOptions))),
174-
}
171+
public async listPrompts(params?: ListPromptsRequest['params']): Promise<ListPromptsResult> {
172+
const allPrompts = await Promise.all(this.prompts.map(async promptOptions => listPrompt(promptOptions)))
173+
const { nextCursor, result: prompts } = withPagination(allPrompts, params)
174+
175+
return { nextCursor, prompts }
175176
}
176177

177-
// TODO: support params (cursor)
178178
/** @see {@link https://modelcontextprotocol.io/specification/2025-03-26/server/resources#listing-resources} */
179-
public async listResources(_params: ListResourcesRequest['params']): Promise<ListResourcesResult> {
180-
return {
181-
resources: this.resources.map(resource => listResource(resource)),
182-
}
179+
public async listResources(params: ListResourcesRequest['params']): Promise<ListResourcesResult> {
180+
const allResources = this.resources.map(resource => listResource(resource))
181+
const { nextCursor, result: resources } = withPagination(allResources, params)
182+
183+
return { nextCursor, resources }
183184
}
184185

185-
// TODO: support params (cursor)
186186
/** @see {@link https://modelcontextprotocol.io/specification/2025-03-26/server/resources#resource-templates} */
187-
public async listResourceTemplates(_params?: ListResourceTemplatesRequest['params']): Promise<ListResourceTemplatesResult> {
188-
return {
189-
resourceTemplates: this.resourceTemplates,
190-
}
187+
public async listResourceTemplates(params?: ListResourceTemplatesRequest['params']): Promise<ListResourceTemplatesResult> {
188+
const allResourceTemplates = this.resourceTemplates
189+
const { nextCursor, result: resourceTemplates } = withPagination(allResourceTemplates, params)
190+
191+
return { nextCursor, resourceTemplates }
191192
}
192193

193-
// TODO: support params (cursor)
194194
/** @see {@link https://spec.modelcontextprotocol.io/specification/2025-03-26/server/tools/#listing-tools} */
195-
public async listTools(_params?: ListToolsRequest['params']): Promise<ListToolsResult> {
196-
return {
197-
tools: await Promise.all(this.tools.map(async toolOptions => listTool(toolOptions))),
198-
}
195+
public async listTools(params?: ListToolsRequest['params']): Promise<ListToolsResult> {
196+
const allTools = await Promise.all(this.tools.map(async toolOptions => listTool(toolOptions)))
197+
const { nextCursor, result: tools } = withPagination(allTools, params)
198+
199+
return { nextCursor, tools }
199200
}
200201

201202
public async ping() {

0 commit comments

Comments
 (0)