@access-mcp/shared 0.3.2 → 0.3.3

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.
@@ -8,8 +8,8 @@ describe("Utils", () => {
8
8
  test("should keep valid characters", () => {
9
9
  expect(sanitizeGroupId("test.group-123")).toBe("test.group-123");
10
10
  });
11
- test("should handle empty string", () => {
12
- expect(sanitizeGroupId("")).toBe("");
11
+ test("should throw error for empty string", () => {
12
+ expect(() => sanitizeGroupId("")).toThrow("groupId parameter is required and cannot be null or undefined");
13
13
  });
14
14
  });
15
15
  describe("formatApiUrl", () => {
@@ -28,6 +28,18 @@ export declare abstract class BaseAccessServer {
28
28
  * Handle get prompt requests - override in subclasses
29
29
  */
30
30
  protected handleGetPrompt(request: any): Promise<any>;
31
+ /**
32
+ * Helper method to create a standard error response (MCP 2025 compliant)
33
+ * @param message The error message
34
+ * @param hint Optional suggestion for how to fix the error
35
+ */
36
+ protected errorResponse(message: string, hint?: string): {
37
+ content: {
38
+ type: "text";
39
+ text: string;
40
+ }[];
41
+ isError: boolean;
42
+ };
31
43
  /**
32
44
  * Helper method to create a JSON resource response
33
45
  * @param uri The resource URI
@@ -78,9 +78,12 @@ export class BaseAccessServer {
78
78
  content: [
79
79
  {
80
80
  type: "text",
81
- text: `Error: ${errorMessage}`,
81
+ text: JSON.stringify({
82
+ error: errorMessage
83
+ }),
82
84
  },
83
85
  ],
86
+ isError: true,
84
87
  };
85
88
  }
86
89
  });
@@ -140,6 +143,25 @@ export class BaseAccessServer {
140
143
  async handleGetPrompt(request) {
141
144
  throw new Error("Prompt not found");
142
145
  }
146
+ /**
147
+ * Helper method to create a standard error response (MCP 2025 compliant)
148
+ * @param message The error message
149
+ * @param hint Optional suggestion for how to fix the error
150
+ */
151
+ errorResponse(message, hint) {
152
+ return {
153
+ content: [
154
+ {
155
+ type: "text",
156
+ text: JSON.stringify({
157
+ error: message,
158
+ ...(hint && { hint }),
159
+ }),
160
+ },
161
+ ],
162
+ isError: true,
163
+ };
164
+ }
143
165
  /**
144
166
  * Helper method to create a JSON resource response
145
167
  * @param uri The resource URI
package/dist/types.d.ts CHANGED
@@ -1,58 +1,25 @@
1
- import { z } from "zod";
2
- export declare const AffinityGroupSchema: z.ZodObject<{
3
- group_id: z.ZodString;
4
- name: z.ZodOptional<z.ZodString>;
5
- description: z.ZodOptional<z.ZodString>;
6
- }, "strip", z.ZodTypeAny, {
7
- group_id: string;
8
- name?: string | undefined;
9
- description?: string | undefined;
10
- }, {
11
- group_id: string;
12
- name?: string | undefined;
13
- description?: string | undefined;
14
- }>;
15
- export declare const EventSchema: z.ZodObject<{
16
- id: z.ZodString;
17
- title: z.ZodString;
18
- description: z.ZodOptional<z.ZodString>;
19
- start_date: z.ZodOptional<z.ZodString>;
20
- end_date: z.ZodOptional<z.ZodString>;
21
- location: z.ZodOptional<z.ZodString>;
22
- }, "strip", z.ZodTypeAny, {
23
- title: string;
24
- id: string;
25
- description?: string | undefined;
26
- start_date?: string | undefined;
27
- end_date?: string | undefined;
28
- location?: string | undefined;
29
- }, {
30
- title: string;
31
- id: string;
32
- description?: string | undefined;
33
- start_date?: string | undefined;
34
- end_date?: string | undefined;
35
- location?: string | undefined;
36
- }>;
37
- export declare const KnowledgeBaseResourceSchema: z.ZodObject<{
38
- id: z.ZodString;
39
- title: z.ZodString;
40
- content: z.ZodOptional<z.ZodString>;
41
- category: z.ZodOptional<z.ZodString>;
42
- tags: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
43
- }, "strip", z.ZodTypeAny, {
44
- title: string;
45
- id: string;
46
- content?: string | undefined;
47
- category?: string | undefined;
48
- tags?: string[] | undefined;
49
- }, {
50
- title: string;
51
- id: string;
52
- content?: string | undefined;
53
- category?: string | undefined;
54
- tags?: string[] | undefined;
55
- }>;
56
- export type AffinityGroup = z.infer<typeof AffinityGroupSchema>;
57
- export type Event = z.infer<typeof EventSchema>;
58
- export type KnowledgeBaseResource = z.infer<typeof KnowledgeBaseResourceSchema>;
1
+ export interface UniversalSearchParams {
2
+ query?: string;
3
+ id?: string;
4
+ type?: string;
5
+ tags?: string[];
6
+ date?: "today" | "upcoming" | "past" | "this_week" | "this_month";
7
+ limit?: number;
8
+ offset?: number;
9
+ sort?: string;
10
+ order?: "asc" | "desc";
11
+ }
12
+ export interface UniversalResponse<T> {
13
+ total: number;
14
+ items: T[];
15
+ }
16
+ export interface UniversalResponseWithHints<T> extends UniversalResponse<T> {
17
+ hints?: {
18
+ next?: string;
19
+ tags?: string[];
20
+ };
21
+ }
22
+ export interface StandardErrorResponse {
23
+ error: string;
24
+ hint?: string;
25
+ }
package/dist/types.js CHANGED
@@ -1,21 +1 @@
1
- import { z } from "zod";
2
- export const AffinityGroupSchema = z.object({
3
- group_id: z.string(),
4
- name: z.string().optional(),
5
- description: z.string().optional(),
6
- });
7
- export const EventSchema = z.object({
8
- id: z.string(),
9
- title: z.string(),
10
- description: z.string().optional(),
11
- start_date: z.string().optional(),
12
- end_date: z.string().optional(),
13
- location: z.string().optional(),
14
- });
15
- export const KnowledgeBaseResourceSchema = z.object({
16
- id: z.string(),
17
- title: z.string(),
18
- content: z.string().optional(),
19
- category: z.string().optional(),
20
- tags: z.array(z.string()).optional(),
21
- });
1
+ export {};
package/dist/utils.d.ts CHANGED
@@ -1,3 +1,74 @@
1
1
  export declare function sanitizeGroupId(groupId: string): string;
2
2
  export declare function formatApiUrl(version: string, endpoint: string): string;
3
3
  export declare function handleApiError(error: any): string;
4
+ /**
5
+ * LLM-Friendly Response Utilities
6
+ *
7
+ * These utilities help create responses that guide LLMs through multi-step workflows,
8
+ * provide clear next actions, and improve error handling.
9
+ */
10
+ export interface NextStep {
11
+ action: string;
12
+ description: string;
13
+ tool?: string;
14
+ parameters?: Record<string, any>;
15
+ }
16
+ export interface LLMResponse<T = any> {
17
+ data?: T;
18
+ count?: number;
19
+ next_steps?: NextStep[];
20
+ suggestions?: string[];
21
+ related_tools?: string[];
22
+ context?: Record<string, any>;
23
+ }
24
+ export interface LLMError {
25
+ error: string;
26
+ error_type: "validation" | "not_found" | "api_error" | "invalid_parameter";
27
+ suggestions?: string[];
28
+ next_steps?: NextStep[];
29
+ did_you_mean?: string[];
30
+ related_queries?: string[];
31
+ }
32
+ /**
33
+ * Add helpful next steps to a successful response
34
+ */
35
+ export declare function addNextSteps<T>(data: T, nextSteps: NextStep[]): LLMResponse<T>;
36
+ /**
37
+ * Create an LLM-friendly error response with suggestions
38
+ */
39
+ export declare function createLLMError(error: string, errorType: LLMError["error_type"], options?: {
40
+ suggestions?: string[];
41
+ nextSteps?: NextStep[];
42
+ didYouMean?: string[];
43
+ relatedQueries?: string[];
44
+ }): LLMError;
45
+ /**
46
+ * Add discovery suggestions when returning empty results
47
+ */
48
+ export declare function addDiscoverySuggestions<T>(data: T[], discoverySteps: NextStep[]): LLMResponse<T[]>;
49
+ /**
50
+ * Common next step templates for cross-server consistency
51
+ */
52
+ export declare const CommonNextSteps: {
53
+ discoverResources: {
54
+ action: string;
55
+ description: string;
56
+ tool: string;
57
+ parameters: {
58
+ include_resource_ids: boolean;
59
+ };
60
+ };
61
+ narrowResults: (currentCount: number, suggestedFilters: string[]) => {
62
+ action: string;
63
+ description: string;
64
+ };
65
+ exploreRelated: (relatedTool: string, description: string) => {
66
+ action: string;
67
+ description: string;
68
+ tool: string;
69
+ };
70
+ refineSearch: (suggestions: string[]) => {
71
+ action: string;
72
+ description: string;
73
+ };
74
+ };
package/dist/utils.js CHANGED
@@ -1,4 +1,7 @@
1
1
  export function sanitizeGroupId(groupId) {
2
+ if (!groupId) {
3
+ throw new Error("groupId parameter is required and cannot be null or undefined");
4
+ }
2
5
  return groupId.replace(/[^a-zA-Z0-9.-]/g, "");
3
6
  }
4
7
  export function formatApiUrl(version, endpoint) {
@@ -13,3 +16,65 @@ export function handleApiError(error) {
13
16
  }
14
17
  return error.message || "Unknown API error";
15
18
  }
19
+ /**
20
+ * Add helpful next steps to a successful response
21
+ */
22
+ export function addNextSteps(data, nextSteps) {
23
+ return {
24
+ data,
25
+ next_steps: nextSteps,
26
+ };
27
+ }
28
+ /**
29
+ * Create an LLM-friendly error response with suggestions
30
+ */
31
+ export function createLLMError(error, errorType, options = {}) {
32
+ return {
33
+ error,
34
+ error_type: errorType,
35
+ ...options,
36
+ };
37
+ }
38
+ /**
39
+ * Add discovery suggestions when returning empty results
40
+ */
41
+ export function addDiscoverySuggestions(data, discoverySteps) {
42
+ if (data.length === 0) {
43
+ return {
44
+ data,
45
+ count: 0,
46
+ next_steps: discoverySteps,
47
+ suggestions: [
48
+ "No results found. Try the suggested next steps to discover available options.",
49
+ ],
50
+ };
51
+ }
52
+ return {
53
+ data,
54
+ count: data.length,
55
+ };
56
+ }
57
+ /**
58
+ * Common next step templates for cross-server consistency
59
+ */
60
+ export const CommonNextSteps = {
61
+ discoverResources: {
62
+ action: "discover_resources",
63
+ description: "Find available compute resources to filter by",
64
+ tool: "search_resources",
65
+ parameters: { include_resource_ids: true },
66
+ },
67
+ narrowResults: (currentCount, suggestedFilters) => ({
68
+ action: "narrow_results",
69
+ description: `Currently showing ${currentCount} results. Add filters to narrow down: ${suggestedFilters.join(", ")}`,
70
+ }),
71
+ exploreRelated: (relatedTool, description) => ({
72
+ action: "explore_related",
73
+ description,
74
+ tool: relatedTool,
75
+ }),
76
+ refineSearch: (suggestions) => ({
77
+ action: "refine_search",
78
+ description: `Try these refinements: ${suggestions.join(", ")}`,
79
+ }),
80
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@access-mcp/shared",
3
- "version": "0.3.2",
3
+ "version": "0.3.3",
4
4
  "description": "Shared utilities for ACCESS-CI MCP servers",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",