Skip to main content
Glama
hichana

Goal Story MCP Server

by hichana

goalstory_create_steps

Generate and organize actionable steps for achieving specific goals. Define sequential tasks, review clarity, and confirm refinements through structured discussions.

Instructions

Formulate actionable steps for a goal through thoughtful discussion. Present the steps for user review either before or after saving, ensuring they're clear and achievable. Confirm if any refinements are needed. IMPORTANT: Steps are ordered by their 'order_ts' timestamp in ascending order - the step with the earliest timestamp becomes step 1, and steps with later timestamps follow in sequence. The first item in your array will receive the earliest timestamp (becoming step 1), and subsequent items will receive progressively later timestamps. NOTE: Array order determines step sequence - first array item = step 1, second array item = step 2, etc.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
goal_idYesUnique identifier of the goal these steps will help achieve.
stepsYesList of clear, actionable step descriptions in sequence. The first item in this array will become step 1, the second will become step 2, and so on based on timestamp ordering.

Implementation Reference

  • MCP server.tool registration and inline anonymous handler function that executes the tool: POSTs to /steps API endpoint with goal_id and steps (converting comma-separated strings for local dev), returns formatted JSON response with ordering explanation.
    server.tool( CREATE_STEPS_TOOL.name, CREATE_STEPS_TOOL.description, CREATE_STEPS_TOOL.inputSchema.shape, async (args) => { const url = `${GOALSTORY_API_BASE_URL}/steps`; // when developing locally, we can pass in a list of strings in the MCP // inspector like this: step1, step2 let steps = args.steps; if (typeof steps === "string") { const itemsAreAString = steps as string; steps = itemsAreAString .split(",") .map((s) => s.trim()) .filter((s) => s.length > 0); } const body = { goal_id: args.goal_id, steps, }; const result = await doRequest(url, "POST", body); return { content: [ { type: "text", text: `Steps created:\n${JSON.stringify(result, null, 2)}\n\nNOTE: Steps are ordered by their 'order_ts' timestamp in ascending order - the step with the smallest timestamp value (updated first) is step 1. The steps appear in order, with the first step having the smallest timestamp. Example: If step A has timestamp 12:00 and step B has timestamp 12:01, then step A is step 1 and step B is step 2.`, }, ], isError: false, }; }, );
  • Tool definition object including name, description, and Zod inputSchema used for registration and validation.
    export const CREATE_STEPS_TOOL = { name: "goalstory_create_steps", description: `Formulate actionable steps for a goal through thoughtful discussion. Present the steps for user review either before or after saving, ensuring they're clear and achievable. Confirm if any refinements are needed. IMPORTANT: Steps are ordered by their 'order_ts' timestamp in ascending order - the step with the earliest timestamp becomes step 1, and steps with later timestamps follow in sequence. The first item in your array will receive the earliest timestamp (becoming step 1), and subsequent items will receive progressively later timestamps. NOTE: Array order determines step sequence - first array item = step 1, second array item = step 2, etc.`, inputSchema: z.object({ goal_id: z .string() .describe("Unique identifier of the goal these steps will help achieve."), steps: z .array(z.string()) .describe( "List of clear, actionable step descriptions in sequence. The first item in this array will become step 1, the second will become step 2, and so on based on timestamp ordering.", ), }), };
  • TypeScript interface defining the input shape for the tool.
    export interface GoalstoryCreateStepsInput { goal_id: string; steps: string[]; }
  • src/index.ts:445-479 (registration)
    MCP server.tool call that registers the tool with name, description, input schema, and handler function.
    server.tool( CREATE_STEPS_TOOL.name, CREATE_STEPS_TOOL.description, CREATE_STEPS_TOOL.inputSchema.shape, async (args) => { const url = `${GOALSTORY_API_BASE_URL}/steps`; // when developing locally, we can pass in a list of strings in the MCP // inspector like this: step1, step2 let steps = args.steps; if (typeof steps === "string") { const itemsAreAString = steps as string; steps = itemsAreAString .split(",") .map((s) => s.trim()) .filter((s) => s.length > 0); } const body = { goal_id: args.goal_id, steps, }; const result = await doRequest(url, "POST", body); return { content: [ { type: "text", text: `Steps created:\n${JSON.stringify(result, null, 2)}\n\nNOTE: Steps are ordered by their 'order_ts' timestamp in ascending order - the step with the smallest timestamp value (updated first) is step 1. The steps appear in order, with the first step having the smallest timestamp. Example: If step A has timestamp 12:00 and step B has timestamp 12:01, then step A is step 1 and step B is step 2.`, }, ], isError: false, }; }, );
  • Shared utility function doRequest used by the handler to make authenticated HTTP requests to the GoalStory API.
    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