Skip to main content
Glama
hichana

Goal Story MCP Server

by hichana

goalstory_read_stories

Retrieve personalized stories for specific goals and steps to support reflection and maintain motivation during goal achievement.

Instructions

Access the collection of personalized stories created for a specific goal/step pair, supporting reflection and motivation.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
goal_idYesUnique identifier of the goal whose stories to retrieve.
step_idYesUnique identifier of the step whose stories to retrieve.
pageNoPage number for viewing subsets of stories (starts at 1).
limitNoMaximum number of stories to return per page.

Implementation Reference

  • The core handler function for the 'goalstory_read_stories' tool. It takes input arguments, builds query parameters for goal_id and step_id (with optional pagination), performs a GET request to the backend API endpoint /stories, and returns the retrieved stories data formatted as a text response.
    server.tool(
      READ_STORIES_TOOL.name,
      READ_STORIES_TOOL.description,
      READ_STORIES_TOOL.inputSchema.shape,
      async (args) => {
        const params = new URLSearchParams();
        params.set("goal_id", args.goal_id);
        params.set("step_id", args.step_id);
        if (args.page) params.set("page", `${args.page}`);
        if (args.limit) params.set("limit", `${args.limit}`);
        const url = `${GOALSTORY_API_BASE_URL}/stories?${params.toString()}`;
        const result = await doRequest(url, "GET");
        return {
          content: [
            {
              type: "text",
              text: `Stories:\n${JSON.stringify(result, null, 2)}`,
            },
          ],
          isError: false,
        };
      },
    );
  • Zod input schema definition for the tool, specifying parameters goal_id, step_id, and optional pagination (page, limit). This schema is passed to the MCP server.tool registration.
    export const READ_STORIES_TOOL = {
      name: "goalstory_read_stories",
      description:
        "Access the collection of personalized stories created for a specific goal/step pair, supporting reflection and motivation.",
      inputSchema: z.object({
        goal_id: z
          .string()
          .describe("Unique identifier of the goal whose stories to retrieve."),
        step_id: z
          .string()
          .describe("Unique identifier of the step whose stories to retrieve."),
        page: z
          .number()
          .optional()
          .describe("Page number for viewing subsets of stories (starts at 1)."),
        limit: z
          .number()
          .optional()
          .describe("Maximum number of stories to return per page."),
      }),
    };
  • TypeScript interface defining the input shape for the tool, matching the Zod schema.
    export interface GoalstoryReadStoriesInput {
      goal_id: string;
      step_id: string;
      page?: number;
      limit?: number;
    }
  • Shared helper function used by all tool handlers to make authenticated HTTP requests to the GoalStory API backend, with logging, timeout handling, and comprehensive error management.
    async function doRequest<T = any>(
      url: string,
      method: string,
      body?: unknown,
    ): Promise<T> {
      console.error("Making request to:", url);
      console.error("Method:", method);
      console.error("Body:", body ? JSON.stringify(body) : "none");
    
      try {
        const response = await axios({
          url,
          method,
          headers: {
            "Content-Type": "application/json",
            Authorization: `Bearer ${GOALSTORY_API_TOKEN}`,
          },
          data: body,
          timeout: 10000, // 10 second timeout
          validateStatus: function (status) {
            return status >= 200 && status < 500; // Accept all status codes less than 500
          },
        });
        console.error("Response received:", response.status);
        return response.data as T;
      } catch (err) {
        console.error("Request failed with error:", err);
    
        if (axios.isAxiosError(err)) {
          if (err.code === "ECONNABORTED") {
            throw new Error(
              `Request timed out after 10 seconds. URL: ${url}, Method: ${method}`,
            );
          }
          if (err.response) {
            // The request was made and the server responded with a status code
            // that falls out of the range of 2xx
            throw new Error(
              `HTTP Error ${
                err.response.status
              }. URL: ${url}, Method: ${method}, Body: ${JSON.stringify(
                body,
              )}. Error text: ${JSON.stringify(err.response.data)}`,
            );
          } else if (err.request) {
            // The request was made but no response was received
            throw new Error(
              `No response received from server. URL: ${url}, Method: ${method}`,
            );
          } else {
            // Something happened in setting up the request that triggered an Error
            throw new Error(`Request setup failed: ${err.message}`);
          }
        } else {
          // Something else happened
          throw new Error(
            `Unexpected error: ${err instanceof Error ? err.message : String(err)}`,
          );
        }
      }
    }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/hichana/goalstory-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server